2013-09-02 12 views
18

私は、いくつかのテストおよびステージングシステムとさまざまな開発者ワークステーションに既にデプロイされているアプリケーションを開発中です。追加の参照データを追加する必要がありますが、追加する方法がわかりません。既存のレールデータベースに新しいシードデータを追加する方法

ほとんどのアドバイスではseed.rbを使用していますが、これはアプリケーションが最初にデプロイされたときに一度だけ実行されることです。 1行の参照データを追加できるように、テストとステージングのデータベースを再構築する必要はないので、データを追加する別の方法はありますか?

私はDBの移行を使用して考えていますが、これは正しいアプローチですか?

おかげ

+2

あなたが望むように 'seed.rb'を実行することができます。これは普通のルビスクリプトファイルです...前に実行したものを再度実行すれば、重複が発生することに注意してください。あなたのケースでは、データの行を追加して「レーキタスク」を使用するか、スクリプトランナーを使用する場合は、http://guides.rubyonrails.org/command_line.html#rails-runner私は移行が適切であるとは思わないこれでも。 – j03w

答えて

26

seed.rbファイルを構造化して、進行中のデータの作成と更新を可能にします。シードファイルを1回だけ実行することに限定されず、最初のデプロイメントにしか使用されないと思われる場合は、参照データの設定時に提供できる柔軟性が欠落します。

シードファイルは、ちょうどあなたのようなことを行うことができますので、ルビー:それは存在しないか、それはいくつかを見つけた場合、データを更新しない場合、これは新しいデータが作成されます

user = User.find_or_initialize_by(email: '[email protected]') 
user.name = 'Bob' 
user.password = 'secret' 
user.role = 'manager' 
user.save! 

シードファイルを正しく構成すると、依存オブジェクトを作成して更新することもできます。

bang saveを使用して、オブジェクトを保存できない場合に例外が発生するようにすることをおすすめします。これは、シードをデバッグする最も簡単な方法です。

私はseedbank gemを使用して、環境、依存するシードなどのデータを設定するなど、シードデータにさらに多くの構造を提供します。

シードデータにマイグレーションを使用することはお勧めしません。柔軟性の欠如(たとえば、シード・データをたった一つの環境にターゲティングする方法)と、特定の環境をリフレッシュするためにいつでも実行できる再利用可能なデータ・セットを構築する実際の方法はありません。また、スキーマへの参照がない一連の移行があり、新しいデータを生成するか、現在のデータを変更するたびに新しい移行を作成する必要があります。

+0

@ nmott-上記のようなコンテンツを追加したら、rake db:seedを実行する必要がありますか?もし私が好きなら、既存のものもまた人口に住んでいますか? – Sam

+2

@ Jsdはい、 'rake db:seed'はシードファイルをロードします。特定のモデルがすでに存在する場合、レコードを見つけてシードファイルのデータで上書きします。つまり、アプリ内のデータを変更し、シードファイルを使用して標準データセットに定期的に更新することができます。 – nmott

+0

これは最終的にかなり時間がたつにつれ肥大化するようです。 –

2

あなたは移行を使用することができますが、それはあなたが持っている最も安全な選択肢ではありません。 たとえば、移行を介してテーブルにレコードを追加した後、将来そのテーブルのスキーマを変更するとします。アプリをどこかにインストールすると、rake db:migrateを実行することができなくなります。

完全に移行されたスキーマでrake db:seedを実行できるので、種は常にお勧めします。

レコード用の場合は、レールコンソールをご利用ください。

1

それはseed.rbによって呼び出さseed.rbで、このような冪等の方法または別のタスクを使用するのが最善です:@ nmottさんに

Contact.find_by_email("[email protected]") || Contact.create(email: "[email protected]", phone: "202-291-1970", created_by: "System") 
# This saves you an update to the DB if the record already exists. 

または類似の:

Contact.find_or_initialize_by_email("[email protected]").update_attributes(phone: "202-291-1970", created_by: "System") 
# this performs an update regardless, but it may be useful if you want to reset your data. 

またはその代わりにassign_attributesを使用保存する前に複数の属性を割り当てる場合は、update_attributesを入力します。

0

私は与えられたIDを持つリストの項目は、すでにそれは例外を返しますが存在する場合は、我々はその項目を削除するまで、もう一度それを試してseed.rb

users_list = [ 
    {id: 1, name: "Diego", age: "25"}, 
    {id: 2, name: "Elano", age: "27"} 
] 

while !users_list.empty? do 
    begin 
    User.create(users_list) 
    rescue 
    users_list = users_list.drop(1) #removing the first if the id already exist. 
    end 
end 

にこのような何かをしましたusers_list配列が空です。

この方法では、オブジェクトをインクルードする前に各オブジェクトを検索する必要はありませんが、@ nmottコードのようにすでに挿入されている値を更新することはできません。

0

seeds.dbを変更する代わりに、新しいデータベースのシードに使用したいと思うかもしれませんが、カスタムレイクタスク(RailsCast #66 Custom Rake Tasks)を作成することができます。

必要な数のRakeタスクを作成できます。たとえば、アプリケーションのバージョン1.0を実行するサーバーと、1.1を実行するサーバーの2つのサーバーがあり、両方を1.2にアップグレードしたいとします。アプリのバージョンによって異なるコードが必要な場合があるので、lib/tasks/1-0-to-1-2.rakelib/tasks`1-1-to-1-2.rakeを作成できます。

1

シードファイルを使用して、常に新しいテーブルまたは既存のテーブルにインスタンスを追加します。私の解決策は簡単です。私はdb/seeds.rbファイル内の他のすべてのシードデータをコメントアウトして、新しいシードデータだけがライブコードになるようにします。次にbin/rake db:seedを実行します。

関連する問題