在Rails中创建数据库的最佳方式是什么?

时间:2022-09-15 20:51:40

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/fixture中的文件中有一堆create语句,以及一个处理它们的rake任务。例如,我有一个模型是主题。我有一个主题。在/db/fixture中的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无效。这意味着,如果我决定添加一个主题,让我们称它为“Red”,那么我只需要将主题语句添加到这个fixture文件中,并调用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.

我将真诚地感谢那些包含了最佳实践的长时间思考的答案。

8 个解决方案

#1


102  

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

注意,如果您已经创建了fixture,那么您可以通过在seed中加入以下内容来填充db: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")

#2


24  

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.

根据我的经验,我总是遇到需要这两种类型的数据。因此,我把一个小的gem放在一起,它扩展了Rails的种子,让你在db/seed /以及db/seed /ENV下的任何环境种子数据(例如db/seed /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转储一样,fixture是脆弱的、易维护的。

#3


24  

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_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一起使用时,它可以用关联来快速填充数据库,而不必使用fixture (yuck)。

I have code like this in a rake task.

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

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

#4


21  

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

使用种子。rb文件或FactoryBot是很棒的,但是它们对于固定的数据结构和测试是非常好的。

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任务,您还可以定义种子之间的依赖关系。您的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

#5


1  

Instead of using explicit creates, use YAML files. With a simple syntax, you can fill in all the values of an object. Actually, if you know anything about rails testing, that's the standard way to seed the test database. Check out these pages:
http://railspikes.com/2008/2/1/loading-seed-data http://quotedprintable.com/2007/11/16/seed-data-in-rails

与其使用显式创建,不如使用YAML文件。使用简单的语法,您可以填充对象的所有值。实际上,如果您对rails测试有所了解,那么这就是生成测试数据库的标准方法。查看这些页面:http://railspikes.com/2008/2/1/loadingseeed -data http://quotedprintable.com/2007/11/16/seeed -data in-rails

#6


1  

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.

另一种方法是将宝石用于更高级或更容易的播种,如:种子库。

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.

在谷歌上添加一个最新的答案。

#7


-1  

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设置上出错。

#8


-4  

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.

注意:请记住,夹具可以直接插入,也不要使用您的模型,所以如果您有回调,那么您需要找到一个解决方案。

#1


102  

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

注意,如果您已经创建了fixture,那么您可以通过在seed中加入以下内容来填充db: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")

#2


24  

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.

根据我的经验,我总是遇到需要这两种类型的数据。因此,我把一个小的gem放在一起,它扩展了Rails的种子,让你在db/seed /以及db/seed /ENV下的任何环境种子数据(例如db/seed /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转储一样,fixture是脆弱的、易维护的。

#3


24  

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_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一起使用时,它可以用关联来快速填充数据库,而不必使用fixture (yuck)。

I have code like this in a rake task.

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

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

#4


21  

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

使用种子。rb文件或FactoryBot是很棒的,但是它们对于固定的数据结构和测试是非常好的。

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任务,您还可以定义种子之间的依赖关系。您的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

#5


1  

Instead of using explicit creates, use YAML files. With a simple syntax, you can fill in all the values of an object. Actually, if you know anything about rails testing, that's the standard way to seed the test database. Check out these pages:
http://railspikes.com/2008/2/1/loading-seed-data http://quotedprintable.com/2007/11/16/seed-data-in-rails

与其使用显式创建,不如使用YAML文件。使用简单的语法,您可以填充对象的所有值。实际上,如果您对rails测试有所了解,那么这就是生成测试数据库的标准方法。查看这些页面:http://railspikes.com/2008/2/1/loadingseeed -data http://quotedprintable.com/2007/11/16/seeed -data in-rails

#6


1  

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.

另一种方法是将宝石用于更高级或更容易的播种,如:种子库。

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.

在谷歌上添加一个最新的答案。

#7


-1  

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设置上出错。

#8


-4  

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.

注意:请记住,夹具可以直接插入,也不要使用您的模型,所以如果您有回调,那么您需要找到一个解决方案。