86

我有一个 rake 任务,它在我的 rails 应用程序中填充一些初始数据。例如,国家、州、移动运营商等。

我现在设置它的方式是,我在 /db/fixtures 的文件中有一堆创建语句和一个处理它们的 rake 任务。例如,我拥有的一个模型是主题。我在 /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 不起作用。这意味着如果我决定添加一个主题,我们称之为“红色”,那么我只想将主题语句添加到这个夹具文件并调用 rake 任务来重新设置数据库。如果我这样做,因为主题属于其他对象,并且在重新初始化时它们的 id 会发生变化,所有链接都会被破坏。

我的问题首先是,这是处理数据库播种的好方法吗?在之前的帖子中,这是推荐给我的。

如果是这样,我怎样才能对 ID 进行硬编码,这有什么缺点吗?

如果不是,那么播种数据库的最佳方法是什么?

我将真正欣赏包含最佳实践的长而深思熟虑的答案。

4

7 回答 7

116

更新,因为这些答案有些过时(尽管有些仍然适用)。

rails 2.3.4 中添加的简单功能,db/seeds.rb

提供新的 rake 任务

rake db:seed

适合填充常见的静态记录,如州、国家等......

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

*请注意,如果您已经创建了固定装置,也可以使用 db:seed 任务填充,方法是将以下内容放入您的 seed.rb 文件(来自 railscast 剧集):

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

对于 Rails 3.x 使用 'ActiveRecord::Fixtures' 而不是 'Fixtures' 常量

require 'active_record/fixtures'
ActiveRecord::Fixtures.create_fixtures("#{Rails.root}/test/fixtures", "fixtures_file_name")
于 2010-01-15T10:38:52.803 回答
29

通常需要两种类型的种子数据。

  • 应用程序核心可能依赖的基本数据。我称之为普通种子。
  • 环境数据,例如开发应用程序,拥有一组已知状态的数据,我们可以使用这些数据在本地处理应用程序(上面的 Factory Girl 答案涵盖了这种数据)。

根据我的经验,我总是遇到对这两种数据的需求。因此,我将一个小 gem 放在一起,它扩展了 Rails 的种子,并允许您在 db/seeds/ 下添加多个通用种子文件,并在 db/seeds/ENV 下添加任何环境种子数据,例如 db/seeds/development。

我发现这种方法足以为我的种子数据提供一些结构,并让我能够通过运行将我的开发或暂存环境设置为已知状态:

rake db:setup

固定装置很脆弱,难以维护,常规的 sql 转储也是如此。

于 2011-04-04T00:03:46.547 回答
27

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 (yuck)。

我在 rake 任务中有这样的代码。

100.times do
    Factory(:company, :address => Factory(:address), :employees => [Factory(:employee)])
end
于 2009-04-17T19:33:18.860 回答
27

使用seeds.rbfile orFactoryBot很好,但它们分别适用于固定数据结构和测试。

seedbankgem 可以为您的种子提供更多的控制和模块化。它插入 rake 任务,您还可以定义种子之间的依赖关系。您的 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
于 2013-11-26T07:54:18.640 回答
1

Rails 有一种内置的方式来播种数据,如此所述。

另一种方法是使用 gem 进行更高级或更简单的播种,例如:seedbank

这个 gem 的主要优点和我使用它的原因是它具有高级功能,例如数据加载依赖项和每个环境的种子数据。

添加一个最新的答案,因为这个答案首先在谷歌上。

于 2014-05-05T14:21:40.637 回答
-3

最好的方法是使用固定装置。

注意:请记住,夹具会直接插入并且不使用您的模型,因此如果您有填充数据的回调,则需要找到解决方法。

于 2009-04-17T19:10:58.587 回答
-5

将其添加到数据库迁移中,这样每个人都可以在更新时获得它。在 ruby​​/rails 代码中处理您的所有逻辑,因此您永远不必搞乱显式 ID 设置。

于 2009-04-17T19:13:32.060 回答