web-dev-qa-db-ja.com

Railsでデータベースをシードする最良の方法は何ですか?

Railsアプリに初期データを入力するレーキタスクがあります。たとえば、国、州、携帯電話会社など。

現在の設定方法は、/ db/fixtures内のファイルに多数のcreateステートメントがあり、それらを処理するrakeタスクがあることです。たとえば、私が持っているモデルの1つはテーマです。/db/fixturesには、次のようなtheme.rbファイルがあります。

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"

ここでのアイデアは、ユーザーが最初から利用できるストックテーマをいくつかインストールすることです。この方法に問題があります。

IDの設定は機能しません。つまり、テーマを追加することに決めた場合、「Red」と呼び、このフィクスチャファイルにテーマステートメントを追加し、rakeタスクを呼び出してデータベースを再シードするだけです。私がそうすると、テーマは他のオブジェクトに属し、その再初期化時にIDが変更されるため、すべてのリンクが壊れます。

私の質問はまず第一に、これはデータベースのシードを処理する良い方法ですか?以前の投稿で、これは私に勧められました。

もしそうなら、どのようにIDをハードコーディングできますか、それには欠点がありますか?

そうでない場合、データベースをシードする最良の方法は何ですか?

ベストプラクティスを取り入れた、長く考え抜かれた答えに心から感謝します。

76
Tony

これらの回答は少し時代遅れであるため更新します(ただし、一部はまだ適用されます)。

Rails 2.3.4、db/seeds.rbに追加されたシンプルな機能

新しいレーキタスクを提供します

rake db:seed

州、国などの一般的な静的レコードを作成するのに適しています...

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

*既にrailscastエピソードからseeds.rbファイルに以下を追加することでdb:seedタスクを取り込むためにフィクスチャーを作成している場合は、フィクスチャーを使用できることに注意してください。

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

Rails 3.xは、 'Fixtures'定数の代わりに 'ActiveRecord :: Fixtures'を使用します

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

通常、2種類のシードデータが必要です。

  • アプリケーションのコアが依存する可能性のある基本データ。これを共通の種と呼びます。
  • 環境データ、たとえばアプリを開発する場合、アプリでローカルに作業するために使用できる既知の状態のデータの束を持つことが有用です(上記のファクトリーガールの回答は、この種のデータを対象としています)。

私の経験では、これらの2種類のデータの必要性に常に出くわしていました。 Railsのシードを拡張する小さなgem を組み合わせて、db/seeds /の下に複数の共通シードファイルを追加し、db/seeds/ENVの下に環境シードデータを追加します(例:db/seeds/development) 。

このアプローチは、シードデータに何らかの構造を与えるのに十分であり、次のコマンドを実行するだけで、開発環境またはステージング環境を既知の状態にセットアップすることができます。

rake db:setup

通常のSQLダンプと同様に、フィクスチャは壊れやすく、保守が困難です。

27
james2m

factory_bot それはあなたが達成しようとしていることをするように聞こえます。デフォルト定義ですべての共通属性を定義し、作成時にそれらをオーバーライドできます。ファクトリにidを渡すこともできます。

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')

Fakerを使用すると、Fixtures(いや)をいじる必要なく、データベースに関連付けをすばやく追加できます。

このようなコードはrakeタスクにあります。

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

seeds.rbファイルまたはFactoryBotを使用するのは素晴らしいことですが、これらはそれぞれ固定データ構造とテストに最適です。

seedbank gemを使用すると、シードをより詳細に制御およびモジュール化できます。 rakeタスクを挿入し、シード間の依存関係を定義することもできます。レーキタスクリストには、次の追加項目があります(例)。

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
22
Yuri

Railsには、説明したようにデータをシードするための組み込みの方法があります here

別の方法は、 seedbank のような、より高度な、または簡単なシードにgemを使用することです。

このgemの主な利点と私がそれを使用する理由は、データロードの依存関係や環境ごとのシードデータなどの高度な機能があることです。

この回答がグーグルで最初であったため、最新の回答を追加します。

1
SimonW