Was ist der beste Weg, um eine Datenbank in Rails zu erstellen?


81

Ich habe eine Rake-Aufgabe, die einige Anfangsdaten in meiner Rails-App auffüllt. Zum Beispiel Länder, Staaten, Mobilfunkanbieter usw.

Ich habe es jetzt so eingerichtet, dass ich eine Reihe von Erstellungsanweisungen in Dateien in / db / fixtures und eine Rake-Task habe, die sie verarbeitet. Ein Modell, das ich habe, sind beispielsweise Themen. Ich habe eine theme.rb-Datei in / db / fixtures, die so aussieht:

Theme.delete_all
Theme.create(:id => 1, :name=>'Lite', :background_color=>'0xC7FFD5', :title_text_color=>'0x222222',
                      :component_theme_color=>'0x001277', :carrier_select_color=>'0x7683FF', :label_text_color=>'0x000000',
                      :join_upper_gradient=>'0x6FAEFF', :join_lower_gradient=>'0x000000', :join_text_color=>'0xFFFFFF',
                      :cancel_link_color=>'0x001277', :border_color=>'0x888888', :carrier_text_color=>'0x000000', :public => true)

Theme.create(:id => 2, :name=>'Metallic', :background_color=>'0x000000', :title_text_color=>'0x7299FF',
                      :component_theme_color=>'0xDBF2FF', :carrier_select_color=>'0x000000', :label_text_color=>'0xDBF2FF',
                      :join_upper_gradient=>'0x2B25FF', :join_lower_gradient=>'0xBEFFAC', :join_text_color=>'0x000000',
                      :cancel_link_color=>'0xFF7C12', :border_color=>'0x000000', :carrier_text_color=>'0x000000', :public => true)

Theme.create(:id => 3, :name=>'Blues', :background_color=>'0x0060EC', :title_text_color=>'0x000374',
                      :component_theme_color=>'0x000374', :carrier_select_color=>'0x4357FF', :label_text_color=>'0x000000',
                      :join_upper_gradient=>'0x4357FF', :join_lower_gradient=>'0xffffff', :join_text_color=>'0x000000',
                      :cancel_link_color=>'0xffffff', :border_color=>'0x666666', :carrier_text_color=>'0x000000', :public => true)
puts "Success: Theme data loaded"

Die Idee hier ist, dass ich einige Standardthemen installieren möchte, mit denen Benutzer beginnen können. Ich habe ein Problem mit dieser Methode.

Das Einstellen der ID funktioniert nicht. Das heißt, wenn ich mich entscheide, ein Thema hinzuzufügen, nennen wir es 'Rot', dann möchte ich einfach die Theme-Anweisung zu dieser Fixture-Datei hinzufügen und die Rake-Task aufrufen, um die Datenbank neu zu säen. Wenn ich das mache, weil alle Themen zu anderen Objekten gehören und sich ihre ID bei dieser Neuinitialisierung ändert, sind alle Links unterbrochen.

Meine Frage ist zuallererst, ist dies ein guter Weg, um mit dem Seeding einer Datenbank umzugehen? In einem früheren Beitrag wurde mir dies empfohlen.

Wenn ja, wie kann ich die IDs hart codieren, und gibt es irgendwelche Nachteile?

Wenn nicht, wie kann die Datenbank am besten gesetzt werden?

Ich werde lange und durchdachte Antworten, die Best Practices beinhalten, wirklich zu schätzen wissen.

Antworten:


111

Aktualisierung, da diese Antworten etwas veraltet sind (obwohl einige noch zutreffen).

Einfache Funktion in Schienen 2.3.4, db / seeds.rb hinzugefügt

Bietet eine neue Rechenaufgabe

rake db:seed

Gut zum Auffüllen gängiger statischer Datensätze wie Bundesstaaten, Länder usw.

http://railscasts.com/episodes/179-seed-data

* Beachten Sie, dass Sie Fixtures verwenden können, wenn Sie sie bereits erstellt haben, um sie auch mit der Aufgabe db: seed zu füllen, indem Sie Folgendes in Ihre Datei seeds.rb (aus der Railscast-Episode) einfügen:

require 'active_record/fixtures'
Fixtures.create_fixtures("#{Rails.root}/test/fixtures", "operating_systems")

Verwenden Sie für Rails 3.x 'ActiveRecord :: Fixtures' anstelle der Konstante 'Fixtures'

require 'active_record/fixtures'
ActiveRecord::Fixtures.create_fixtures("#{Rails.root}/test/fixtures", "fixtures_file_name")

27

Normalerweise sind zwei Arten von Saatgutdaten erforderlich.

  • Grunddaten, auf die sich der Kern Ihrer Anwendung stützen kann. Ich nenne das die gemeinsamen Samen.
  • Umgebungsdaten , zum Beispiel um die App zu entwickeln, ist es nützlich, eine Reihe von Daten in einem bekannten Zustand zu haben, die wir für die lokale Arbeit an der App verwenden können (die obige Antwort von Factory Girl deckt diese Art von Daten ab).

Nach meiner Erfahrung bin ich immer auf die Notwendigkeit dieser beiden Datentypen gestoßen. Also habe ich ein kleines Juwel zusammengestellt, das die Samen von Rails erweitert und es Ihnen ermöglicht, mehrere gemeinsame Saatgutdateien unter db / seed / und alle Umwelt-Saatgutdaten unter db / seed / ENV hinzuzufügen, zum Beispiel db / seed / development.

Ich habe festgestellt, dass dieser Ansatz ausreicht, um meinen Seed-Daten eine gewisse Struktur zu verleihen, und mir die Möglichkeit gibt, meine Entwicklungs- oder Staging-Umgebung in einem bekannten Zustand einzurichten, indem ich einfach Folgendes ausführe:

rake db:setup

Die Geräte sind zerbrechlich und flockig, ebenso wie normale SQL-Dumps.


Ich mag die Begriffe "Systemdaten" und "Laufzeitdaten", um Dinge zu beschreiben, auf die sich der Code stützt, wenn er im Vergleich zu Daten von Benutzern vorhanden ist. Manchmal ist die Grenze zwischen ihnen verschwommen.
Tim Abell

25

factory_bot klingt so, als würde es das tun, was Sie erreichen wollen. Sie können alle allgemeinen Attribute in der Standarddefinition definieren und sie dann beim Erstellen überschreiben. Sie können auch eine ID an die Fabrik übergeben:

Factory.define :theme do |t|
  t.background_color '0x000000'
  t.title_text_color '0x000000',
  t.component_theme_color '0x000000'
  t.carrier_select_color '0x000000'
  t.label_text_color '0x000000',
  t.join_upper_gradient '0x000000'
  t.join_lower_gradient '0x000000'
  t.join_text_color '0x000000',
  t.cancel_link_color '0x000000'
  t.border_color '0x000000'
  t.carrier_text_color '0x000000'
  t.public true
end

Factory(:theme, :id => 1, :name => "Lite", :background_color => '0xC7FFD5')
Factory(:theme, :id => 2, :name => "Metallic", :background_color => '0xC7FFD5')
Factory(:theme, :id => 3, :name => "Blues", :background_color => '0x0060EC')

Wenn es mit faker verwendet wird, kann es eine Datenbank sehr schnell mit Assoziationen füllen, ohne mit Fixtures (yuck) herumspielen zu müssen.

Ich habe Code wie diesen in einer Rechenaufgabe.

100.times do
    Factory(:company, :address => Factory(:address), :employees => [Factory(:employee)])
end

10
FactoryGirl ist eigentlich zum Testen anstelle von Vorrichtungen gedacht, kann aber auch zum Laden von Material in die Produktion verwendet werden. Verwenden Sie eine Rake-Task mit db: migrate als Voraussetzung, um alle Standarddaten zu laden. Möglicherweise müssen Sie die Rechenaufgabe so intelligent machen, dass keine Kopien vorhandener Daten erstellt werden.
Bob Aman

2
Die Verwendung von FactoryGirl für Saatgut wird nicht empfohlen. Überprüfen Sie diesen Beitrag .
Blackbiron

24

Die Verwendung von seeds.rbDatei oder FactoryBotist großartig, aber diese eignen sich jeweils hervorragend für feste Datenstrukturen und Tests.

Der seedbankEdelstein gibt Ihnen möglicherweise mehr Kontrolle und Modularität für Ihre Samen. Es fügt Rechenaufgaben ein und Sie können auch Abhängigkeiten zwischen Ihren Seeds definieren. Ihre Rake-Aufgabenliste enthält folgende Ergänzungen (z. B.):

rake db:seed                    # Load the seed data from db/seeds.rb, db/seeds/*.seeds.rb and db/seeds/ENVIRONMENT/*.seeds.rb. ENVIRONMENT is the current environment in Rails.env.
rake db:seed:bar                # Load the seed data from db/seeds/bar.seeds.rb
rake db:seed:common             # Load the seed data from db/seeds.rb and db/seeds/*.seeds.rb.
rake db:seed:development        # Load the seed data from db/seeds.rb, db/seeds/*.seeds.rb and db/seeds/development/*.seeds.rb.
rake db:seed:development:users  # Load the seed data from db/seeds/development/users.seeds.rb
rake db:seed:foo                # Load the seed data from db/seeds/foo.seeds.rb
rake db:seed:original           # Load the seed data from db/seeds.rb

1

Rails verfügt über eine integrierte Methode zum Setzen von Daten, wie hier erläutert .

Ein anderer Weg wäre, einen Edelstein für fortgeschrittenere oder einfachere Aussaat zu verwenden, wie zum Beispiel: Samenbank .

Der Hauptvorteil dieses Edelsteins und der Grund, warum ich es verwende, besteht darin, dass es über erweiterte Funktionen wie Abhängigkeiten beim Laden von Daten und Seed-Daten pro Umgebung verfügt.

Hinzufügen einer aktuellen Antwort, da diese Antwort zuerst bei Google war.


-3

Der beste Weg ist, Scheinwerfer zu verwenden.

Hinweis: Beachten Sie, dass Fixtures direkte Einfügungen durchführen und Ihr Modell nicht verwenden. Wenn Sie also Rückrufe haben, die Daten füllen, müssen Sie eine Problemumgehung finden.


-4

Fügen Sie es bei Datenbankmigrationen hinzu, damit jeder es beim Aktualisieren erhält. Behandeln Sie Ihre gesamte Logik im Ruby / Rails-Code, damit Sie sich nie mit expliziten ID-Einstellungen herumschlagen müssen.


Wenn ich die anfänglichen Daten ändern muss, können die Dinge bei der Verwendung von Migrationen chaotisch werden. Ihr zweiter Kommentar macht nicht wirklich Sinn. Links über Fremdschlüssel werden zerstört
Tony

c = Category.create (stuff) p = Post.create (stuff) p.category = c Es ist nicht erforderlich, IDs explizit festzulegen. Wenn Sie die Anfangsdaten ändern, erstellen Sie einfach eine neue Migration. Ziemlich einfach.
Matt Rogish

Dies setzt voraus, dass die Zuordnungen zum Zeitpunkt der Erstellung des Objekts vorgenommen werden können. Hier ist ein Beispiel, wo ich glaube, dass Ihre Logik versagt ... korrigieren Sie mich, wenn ich falsch liege. Ich setze die DB mit Vorlagenthemen. Benutzer-ID = 1 erstellt die Vorlagen-ID = 2 und mit der Themen-ID = 4. Zu diesem Zeitpunkt befindet sich ein Datensatz wie folgt in der Datenbank: template: id = 2, user_id = 1, theme_id = 4. Wenn ich die Datenbank neu initiiere, ist die Themen-ID = 4 jetzt die Themen-ID = 10 ... und dann ist die Vorlage des Benutzers falsch thematisiert
Tony

Nun, es hängt davon ab, was Sie unter "Neuinitialisieren" verstehen. Wenn Sie bei Null beginnen, behandelt Rails alle Zuordnungen automatisch. Wenn Sie ID-Werte hart codieren (schlecht !!!), wird es ja explodieren.
Matt Rogish

Ok, ich fange an, Ihren Standpunkt zu verstehen, aber ich muss dieses Szenario von Ihnen ausführen. Ich setze die Datenbank mit einer Länder-Nachschlagetabelle. USA => Länder-ID = 1. Dann erstellt ein Benutzer ein Restaurant, das in den USA existiert. Die Zeile der Restaurantdatenbank hat country_id = 1. Das ist sehr häufig, oder? Ich entscheide später, dass ich weitere Länder hinzufügen möchte ... Wenn ich die Datenbank sauber wische und die Länder-Nachschlagetabelle wieder auffülle, ist das Land des Restaurants jetzt nicht mehr korrekt, es sei denn, die ID ist dieselbe. Wie gehe ich damit um?
Tony
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.