Ruby-on-rails 在 Rails 中播种数据库的最佳方法是什么?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/761123/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What is the best way to seed a database in Rails?
提问by Tony
I have a rake task that populates some initial data in my rails app. For example, countries, states, mobile carriers, etc.
我有一个 rake 任务,它在我的 rails 应用程序中填充一些初始数据。例如,国家、州、移动运营商等。
The way I have it set up now, is I have a bunch of create statements in files in /db/fixtures and a rake task that processes them. For example, one model I have is themes. I have a theme.rb file in /db/fixtures that looks like this:
我现在设置它的方式是,我在 /db/fixtures 中的文件中有一堆 create 语句和一个处理它们的 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"
The idea here is that I want to install some stock themes for users to start with. I have a problem with this method.
这里的想法是我想为用户安装一些库存主题。我对这个方法有问题。
Setting the ID does not work. This means that if I decide to add a theme, let's call it 'Red', then I would simply like to add the theme statement to this fixture file and call the rake task to reseed the database. If I do that, because themes belong to other objects and their id's change upon this re-initialization, all links are broken.
设置 ID 不起作用。这意味着,如果我决定添加一个主题,让我们称其为“红色”,那么我只想将主题语句添加到这个夹具文件中,并调用 rake 任务来重新设置数据库的种子。如果我这样做,因为主题属于其他对象,并且在重新初始化时它们的 id 会发生变化,所有链接都将断开。
My question is first of all, is this a good way to handle seeding a database? In a previous post, this was recommended to me.
我的问题首先是,这是处理数据库播种的好方法吗?在之前的帖子中,这是向我推荐的。
If so, how can I hard code the IDs, and are there any downsides to that?
如果是这样,我如何对 ID 进行硬编码,这有什么缺点吗?
If not, what is the best way to seed the database?
如果没有,为数据库做种子的最佳方法是什么?
I will truly appreciate long and thought out answers that incorporate best practices.
我将真正感谢包含最佳实践的长期而深思熟虑的答案。
回答by ajhit406
Updating since these answers are slightly outdated (although some still apply).
更新,因为这些答案有点过时(尽管有些仍然适用)。
Simple feature added in rails 2.3.4, db/seeds.rb
在 rails 2.3.4, db/seeds.rb 中添加的简单功能
Provides a new rake task
提供新的 rake 任务
rake db:seed
Good for populating common static records like states, countries, etc...
适合填充常见的静态记录,如州、国家等...
http://railscasts.com/episodes/179-seed-data
http://railscasts.com/episodes/179-seed-data
*Note that you can use fixtures if you had already created them to also populate with the db:seed task by putting the following in your seeds.rb file (from the railscast episode):
*请注意,如果您已经创建了设备,则可以使用它们来填充 db:seed 任务,方法是将以下内容放入您的 Seed.rb 文件(来自 railscast 剧集):
require 'active_record/fixtures'
Fixtures.create_fixtures("#{Rails.root}/test/fixtures", "operating_systems")
For Rails 3.x use 'ActiveRecord::Fixtures' instead of 'Fixtures' constant
对于 Rails 3.x,使用 'ActiveRecord::Fixtures' 而不是 'Fixtures' 常量
require 'active_record/fixtures'
ActiveRecord::Fixtures.create_fixtures("#{Rails.root}/test/fixtures", "fixtures_file_name")
回答by james2m
Usually there are 2 types of seed data required.
通常需要两种类型的种子数据。
- Basic dataupon which the core of your application may rely. I call this the common seeds.
- Environmental data, for example to develop the app it is useful to have a bunch of data in a known state that us can use for working on the app locally (the Factory Girl answer above covers this kind of data).
- 应用程序的核心可能依赖的基本数据。我称之为普通种子。
- 环境数据,例如,为了开发应用程序,拥有一组处于已知状态的数据非常有用,我们可以使用这些数据在本地处理应用程序(上面的 Factory Girl 回答涵盖了此类数据)。
In my experience I was always coming across the need for these two types of data. So I put together a small gem that extends Rails' seedsand lets you add multiple common seed files under db/seeds/ and any environmental seed data under db/seeds/ENV for example db/seeds/development.
根据我的经验,我总是遇到对这两种类型数据的需求。所以我把一个小 gem放在一起,它扩展了 Rails 的种子,让你在 db/seeds/ 下添加多个常见的种子文件,并在 db/seeds/ENV 下添加任何环境种子数据,例如 db/seeds/development。
I have found this approach is enough to give my seed data some structure and gives me the power to setup my development or staging environment in a known state just by running:
我发现这种方法足以为我的种子数据提供一些结构,并让我能够通过运行以下命令将我的开发或暂存环境设置为已知状态:
rake db:setup
Fixtures are fragile and flakey to maintain, as are regular sql dumps.
固定装置很脆弱且难以维护,就像常规的 sql 转储一样。
回答by Hates_
factory_botsounds like it will do what you are trying to achieve. You can define all the common attributes in the default definition and then override them at creation time. You can also pass an id to the factory:
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')
When used with faker it can populate a database really quickly with associations without having to mess about with Fixtures (yuck).
当与 faker 一起使用时,它可以通过关联非常快速地填充数据库,而不必与 Fixtures 混淆(糟糕)。
I have code like this in a rake task.
我在 rake 任务中有这样的代码。
100.times do
Factory(:company, :address => Factory(:address), :employees => [Factory(:employee)])
end
回答by Yuri
Using seeds.rbfile or FactoryBotis great, but these are respectively great for fixed data structures and testing.
使用seeds.rbfile orFactoryBot很好,但它们分别适用于固定数据结构和测试。
The seedbankgem might give you more control and modularity to your seeds. It inserts rake tasks and you can also define dependencies between your seeds. Your rake task list will have these additions (e.g.):
该seedbank宝石可能会给你更多的控制和模块化你的种子。它插入 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
回答by SimonW
Rails has a built in way to seed data as explained here.
Rails有内置的方法种子数据的解释这里。
Another way would be to use a gem for more advanced or easy seeding such as: seedbank.
另一种方法是使用 gem 进行更高级或更简单的播种,例如:seedbank。
The main advantage of this gem and the reason I use it is that it has advanced capabilities such as data loading dependencies and per environment seed data.
这个 gem 的主要优点以及我使用它的原因是它具有高级功能,例如数据加载依赖项和每个环境种子数据。
Adding an up to date answer as this answer was first on google.
添加最新答案,因为此答案首先出现在 google 上。
回答by p01nd3xt3r
The best way is to use fixtures.
最好的方法是使用夹具。
Note: Keep in mind that fixtures do direct inserts and don't use your model so if you have callbacks that populate data you will need to find a workaround.
注意:请记住,fixture 会直接插入并且不使用您的模型,因此如果您有填充数据的回调,您将需要找到解决方法。
回答by Matt Rogish
Add it in database migrations, that way everyone gets it as they update. Handle all of your logic in the ruby/rails code, so you never have to mess with explicit ID settings.
将它添加到数据库迁移中,这样每个人都可以在更新时获取它。在 ruby/rails 代码中处理您的所有逻辑,因此您永远不必弄乱显式 ID 设置。

