在 Rails 中播种数据库的最佳方法是什么?

发布于 2024-07-16 16:37:47 字数 2175 浏览 7 评论 0原文

我有一个 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 进行硬编码,这有什么缺点吗?

如果没有,为数据库播种的最佳方法是什么?

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

I have a rake task that populates some initial data in my rails app. For example, countries, states, mobile carriers, etc.

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:

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.

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?

If not, what is the best way to seed the database?

I will truly appreciate long and thought out answers that incorporate best practices.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

初与友歌 2024-07-23 16:37:47

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

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

提供新的 rake 任务

rake db:seed

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

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

*请注意,如果您已经创建了固定装置来填充数据库,则可以使用固定装置:通过将以下内容放入 seeds.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")

Updating since these answers are slightly outdated (although some still apply).

Simple feature added in rails 2.3.4, db/seeds.rb

Provides a new rake task

rake db:seed

Good for populating common static records like states, countries, etc...

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

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

For Rails 3.x use 'ActiveRecord::Fixtures' instead of 'Fixtures' constant

require 'active_record/fixtures'
ActiveRecord::Fixtures.create_fixtures("#{Rails.root}/test/fixtures", "fixtures_file_name")
榕城若虚 2024-07-23 16:37:47

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

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

根据我的经验,我总是遇到对这两类数据的需求。 因此,我整理了一个扩展 Rails 种子的小宝石 并允许您在 db/seeds/ 下添加多个常见种子文件以及 db/seeds/ENV 下的任何环境种子数据,例如 db/seeds/development。

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

rake db:setup

Fixtures 很脆弱且难以维护,就像常规的 sql 转储一样。

Usually there are 2 types of seed data required.

  • Basic data upon 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).

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' seeds and lets you add multiple common seed files under db/seeds/ and any environmental seed data under db/seeds/ENV for example 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.

怕倦 2024-07-23 16:37:47

使用 seeds.rb 文件或 FactoryBot 很棒,但它们分别非常适合固定数据结构和测试。

seedbank gem 可能会为您的种子提供更多控制和模块化。 它插入 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

Using seeds.rb file or FactoryBot is great, but these are respectively great for fixed data structures and testing.

The seedbank gem 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.):

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
蓝色星空 2024-07-23 16:37:47

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(恶心)。

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

100.times do
    Factory(:company, :address => Factory(:address), :employees => [Factory(:employee)])
end

factory_bot sounds 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.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).

I have code like this in a rake task.

100.times do
    Factory(:company, :address => Factory(:address), :employees => [Factory(:employee)])
end
稳稳的幸福 2024-07-23 16:37:47

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

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

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

添加最新答案,因为该答案首先出现在 Google 上。

Rails has a built in way to seed data as explained here.

Another way would be to use a gem for more advanced or easy seeding such as: 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.

Adding an up to date answer as this answer was first on google.

謸气贵蔟 2024-07-23 16:37:47

最好的方法是使用夹具。

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

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.

情何以堪。 2024-07-23 16:37:47

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文