Ruby on Rails でフィクスチャを使用してデータをシードすることは危険ですか
-
13-09-2019 - |
質問
データベース(国、地域、通信事業者など)に存在する必要がある初期データを含むフィクスチャがあります。データベースをシードするタスク rake db:seed があります。
namespace :db do
desc "Load seed fixtures (from db/fixtures) into the current environment's database."
task :seed => :environment do
require 'active_record/fixtures'
Dir.glob(RAILS_ROOT + '/db/fixtures/yamls/*.yml').each do |file|
Fixtures.create_fixtures('db/fixtures/yamls', File.basename(file, '.*'))
end
end
end
このタスクではデータベースが完全に消去され、初期データがロードされるため、少し心配です。これが実稼働環境で複数回実行される可能性さえあるという事実は、私を怖がらせます。これは正常なことなのでしょうか、ただ注意する必要がありますか?それとも、人々は通常、このようなタスクを何らかの方法で保護しますか?
解決
播種データが非常に悪い考えである。
備品が検証されておらず、ほとんどのRails開発者はデータベース制約を使用していないので、これはあなたが簡単に本番データベースに挿入され、無効または不完全なデータを得ることができることを意味します。
備品も必ずしも問題ではなく、で動作するように迷惑です、デフォルトで奇妙な主キーIDを設定します。
このためのソリューションがたくさんあります。私の個人的なお気に入りは、単純にレコードを挿入するためのActiveRecordを使用するRubyスクリプトを実行rakeタスクです。これは、3はdb:seed
で行いますRailsのものですが、あなたは簡単にこのを自分で書くことができます。
私はcreate_or_update
と呼ばれるのActiveRecord :: Baseを追加する方法でこれを補完します。これを使用して、私は古いレコードを更新する代わりに、例外をスローする、シードスクリプトを複数回実行することができます。
私は/ <しばらく前に読み込ん種データと呼ばれるこれらの技術についての記事を書きました>。
他のヒント
は、あなたの質問の最初の部分については、はい私はちょうど生産にこのようにタスクを実行するためのいくつかの予防措置を置くと思います。私は私のブートストラップ/播種作業でこのような保護を入れます:
task :exit_or_continue_in_production? do
if Rails.env.production?
puts "!!!WARNING!!! This task will DESTROY " +
"your production database and RESET all " +
"application settings"
puts "Continue? y/n"
continue = STDIN.gets.chomp
unless continue == 'y'
puts "Exiting..."
exit!
end
end
end
私はいくつかのコンテキストのこの要旨を作成しています。
-は、質問の後半部分では通常、あなたが実際には2つのことをしたい:a)は非常に簡単にデータベースを播種し、開発のためのアプリケーションの設定、およびb)運用サーバー上のアプリケーション(のようなブートストラップ:adminユーザーを挿入し、フォルダを作成するアプリケーションは)、などに依存します。
私は、開発中の播種のための器具を使用したい - チームの誰もが、その後アプリで同じデータを見て、どのようなアプリでのはテストで何と一致しています。 (誰もがちょうどレポのクローンを作成し、この一つのタスクを実行することにより、アプリ上で動作することができますので、通常私はrake app:bootstrap
にrake app:seed
、rake gems:install
のrake app:install
などを包む。)
私は、しかし、本番サーバー上に播種/ブートストラップ用器具を使用することはありませんでした。 Railsのdb/seed.rb
は、このタスクのための本当に細かいですが、他の人が指摘したように、あなたはもちろん、あなた自身のrake app:seed
タスクで同じロジックを置くことができます。
3あなたはseed.rbファイルを使用するため、これを解決するレールます。
http://github.com/brynary/rails/commit/4932f7b38f72104819022abca0c952ba6f9888cbする
私たちは、データのシード処理に使用する多くのベスト プラクティスを構築してきました。私たちはシードに大きく依存しており、マルチテナント システムをシードする必要があるため、いくつかの独自の要件があります。私たちが使用したいくつかのベスト プラクティスを次に示します。
- フィクスチャは最適なソリューションではありませんが、それでもシード データを Ruby 以外のものに保存する必要があります。シード データを保存する Ruby コードは繰り返しが多くなる傾向があります。データを解析可能なファイルに保存すると、一貫した方法でシードを処理するための汎用コードを作成できることになります。
- シードを更新する可能性がある場合は、次のような名前のマーカー列を使用します。
code
シード ファイルを実際のデータと照合します。環境間で ID が一貫していることに依存しないでください。 - 既存のシード データの更新をどのように処理するかを考えてください。ユーザーがこのデータを変更した可能性はありますか?その場合、ユーザーの情報をシード データで上書きするのではなく、維持する必要がありますか?
シード処理のいくつかの方法に興味がある場合は、それらの方法を以下の gem にパッケージ化しました。 シードオーマティック.
どのようにデータベースを接種した後だけで本番サーバーからタスクの削除について?
私は面白いアイデアを持っていた...
あなたは、マイグレーション・スタイルファイルを\ DB \種を作成し\て、コメントを追加したらどうます:
ファイル:200907301234_add_us_states.rb
class AddUsStates < ActiveRecord::Seeds
def up
add_to(:states, [
{:name => 'Wisconsin', :abbreviation => 'WI', :flower => 'someflower'},
{:name => 'Louisiana', :abbreviation => 'LA', :flower => 'cypress tree'}
]
end
end
def down
remove_from(:states).based_on(:name).with_values('Wisconsin', 'Louisiana', ...)
end
end
を交互ます:
def up
State.create!( :name => ... )
end
これは、あなたがそれらをより平和的に共存することができるようになるために、移行や種子を実行できるようになります。
の考え?