11

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

我有点担心,因为这个任务会清除我的数据库并加载初始数据。事实上,这甚至可以在生产中不止一次地做,这让我吓坏了。这是正常的吗,我只需要小心吗?还是人们通常会以某种方式保护这样的任务?

4

6 回答 6

18

使用固定装置播种数据是一个非常糟糕的主意。

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

默认情况下,Fixtures 还设置了奇怪的主键 ID,这不一定是问题,但使用起来很烦人。

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

我用添加到 ActiveRecord::Base 的方法来补充这一点,称为create_or_update. 使用它我可以多次运行种子脚本,更新旧记录而不是抛出异常。

不久前,我写了一篇关于这些技术的文章,名为Loading seed data

于 2009-06-14T06:31:57.327 回答
4

对于您问题的第一部分,是的,我只是为在生产中运行这样的任务采取了一些预防措施。我在引导/播种任务中设置了这样的保护:

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:bootstrap(通常我将,rake app:seed rake gems:install等包装成这样,rake app:install所以每个人都可以通过克隆 repo 并运行这个任务来处理应用程序。)

但是,我永远不会在生产服务器上使用固定装置进行播种/引导。Railsdb/seed.rb非常适合这项任务,但您当然可以将相同的逻辑放在您自己的rake app:seed任务中,就像其他人指出的那样。

于 2009-06-14T08:11:27.493 回答
2

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

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

于 2009-06-12T00:44:08.523 回答
2

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

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

如果您对我们播种的某些方式感兴趣,我们已将它们打包到一个名为SeedOmatic的 gem 中。

于 2012-04-26T12:21:58.867 回答
1

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

于 2009-06-12T09:16:26.247 回答
1

我刚刚有了一个有趣的想法...

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

文件: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

这将允许您以允许它们更和平共存的顺序运行迁移和种子。

想法?

于 2009-08-07T19:45:53.247 回答