在Ruby on Rails中使用夹具播种数据是危险的

我有需要驻留在我的数据库(国家,地区,运营商等)的初始数据。 我有一个任务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 

我有点担心,因为这个任务擦除我的数据库干净并加载初始数据。 这甚至可能在生产中不止一次这样做的事实吓跑了我。 这是正常的,我只需要谨慎吗? 或者人们通常以某种方式保护这样的任务?

使用灯具播种数据是一个非常糟糕的主意。

Fixtures未经过validation,并且由于大多数Rails开发人员不使用数据库约束,这意味着您可以轻松地将无效或不完整的数据插入到生产数据库中。

Fixtures也默认设置了奇怪的主键id,这不一定是个问题但是很烦人。

有很多解决方案。 我个人最喜欢的是一个rake任务,它运行一个Ruby脚本,只使用ActiveRecord插入记录。 这就是Rails 3将对db:seed ,但您可以自己轻松编写。

我用一个名为create_or_update ActiveRecord :: Base添加的方法补充了这一点。 使用这个我可以多次运行种子脚本,更新旧记录而不是抛出exception。

我写了一篇关于这些技术的文章,后来称为加载种子数据 。

对于你问题的第一部分,是的,我只是在生产中运行这样的任务时采取了一些预防措施。 我在自举/播种任务中加入了这样的保护:

 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 

我已经为某些背景创建了这个要点 。

对于问题的第二部分 – 通常你真的想要两件事:a)非常容易播种数据库和设置开发应用程序,以及b)在生产服务器上引导应用程序(例如:插入管理员用户,创建文件夹应用程序)取决于等)。

我会在开发中使用灯具进行播种 – 团队中的每个人都会在应用中看到相同的数据,并且应用中的内容与测试中的内容一致。 (通常我将rake app:bootstraprake app:seed rake gems:install等包装到rake app:install这样每个人都可以通过克隆repo并运行这个任务来处理应用程序。)

但是,我永远不会在生产服务器上使用灯具进行播种/引导。 Rails的db/seed.rb对于这个任务来说非常好,但你当然可以在你自己的rake app:seed使用相同的逻辑rake app:seed任务,就像其他人指出的那样。

Rails 3将使用seed.rb文件为您解决此问题。

http://github.com/brynary/rails/commit/4932f7b38f72104819022abca0c952ba6f9888cb

我们已经建立了一系列用于播种数据的最佳实践。 我们严重依赖播种,我们有一些独特的要求,因为我们需要播种多租户系统。 以下是我们使用过的一些最佳做法:

  1. Fixtures不是最好的解决方案,但你仍然应该将种子数据存储在除Ruby之外的其他东西中。 用于存储种子数据的Ruby代码往往会重复,并且将数据存储在可解析文件中意味着您可以编写通用代码以一致的方式处理种子。
  2. 如果您要更新种子,请使用名称类似code的标记列将种子文件与实际数据进行匹配。 永远不要依赖环境之间的id。
  3. 考虑一下如何处理更新现有种子数据。 用户是否有可能修改此数据? 如果是这样,您应该维护用户的信息而不是用种子数据覆盖它吗?

如果您对我们播种的一些方式感兴趣,我们将它们打包成一个名为SeedOMatic的gem。

在播种数据库后,如何从生产服务器上删除任务?

我刚才有一个有趣的想法……

如果您创建了\ db \ seeds \并添加了迁移样式文件,该怎么办:

file: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 

这将允许您按顺序运行迁移和种子,以使它们更加平和地共存。

想法?