Ruby-on-rails 如何(以及是否)使用初始数据填充 Rails 应用程序
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/62201/
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
How (and whether) to populate rails application with initial data
提问by Luke Halliwell
I've got a rails application where users have to log in. Therefore in order for the application to be usable, there must be one initial user in the system for the first person to log in with (they can then create subsequent users). Up to now I've used a migration to add a special user to the database.
我有一个 rails 应用程序,用户必须在其中登录。因此,为了使应用程序可用,系统中必须有一个初始用户供第一个登录的人使用(然后他们可以创建后续用户)。到目前为止,我已经使用迁移将特殊用户添加到数据库中。
After asking this question, it seems that I should be using db:schema:load, rather than running the migrations, to set up fresh databases on new development machines. Unfortunately, this doesn't seem to include the migrations which insert data, only those which set up tables, keys etc.
问这个问题后,我似乎应该使用 db:schema:load,而不是运行迁移,在新的开发机器上设置新的数据库。不幸的是,这似乎不包括插入数据的迁移,只包括那些设置表、键等的迁移。
My question is, what's the best way to handle this situation:
我的问题是,处理这种情况的最佳方法是什么:
- Is there a way to get d:s:l to include data-insertion migrations?
- Should I not be using migrations at all to insert data this way?
- Should I not be pre-populating the database with data at all? Should I update the application code so that it handles the case where there are no users gracefully, and lets an initial user account be created live from within the application?
- Any other options? :)
- 有没有办法让 d:s:l 包含数据插入迁移?
- 我不应该使用迁移以这种方式插入数据吗?
- 我不应该用数据预先填充数据库吗?我是否应该更新应用程序代码,以便它能够优雅地处理没有用户的情况,并允许从应用程序内部实时创建初始用户帐户?
- 还有其他选择吗?:)
采纳答案by Luke Halliwell
I thought I'd summarise some of the great answers I've had to this question, together with my own thoughts now I've read them all :)
我想我会总结我对这个问题的一些很好的答案,连同我自己的想法,现在我已经阅读了它们:)
There are two distinct issues here:
这里有两个不同的问题:
- Should I pre-populate the database with my special 'admin' user? Or should the application provide a way to set up when it's first used?
- How does one pre-populate the database with data? Note that this is a valid question regardless of the answer to part 1: there are other usage scenarios for pre-population than an admin user.
- 我应该用我的特殊“管理员”用户预先填充数据库吗?或者应用程序是否应该提供一种在首次使用时进行设置的方法?
- 如何用数据预先填充数据库?请注意,无论第 1 部分的答案如何,这是一个有效的问题:除了管理员用户之外,还有其他用于预填充的使用场景。
For (1), it seems that setting up the first user from within the application itself is quite a bit of extra work, for functionality which is, by definition, hardly ever used. It may be slightly more secure, however, as it forces the user to set a password of their choice. The best solution is in between these two extremes: have a script (or rake task, or whatever) to set up the initial user. The script can then be set up to auto-populate with a default password during development, and to require a password to be entered during production installation/deployment (if you want to discourage a default password for the administrator).
对于 (1),从应用程序本身设置第一个用户似乎是一项额外的工作,因为根据定义,这些功能几乎从未使用过。然而,它可能稍微更安全,因为它强制用户设置他们选择的密码。最好的解决方案是介于这两个极端之间:使用脚本(或 rake 任务,或其他)来设置初始用户。然后可以将脚本设置为在开发期间自动填充默认密码,并要求在生产安装/部署期间输入密码(如果您不希望管理员使用默认密码)。
For (2), it appears that there are a number of good, valid solutions. A rake task seems a good way, and there are some plugins to make this even easier. Just look through some of the other answers to see the details of those :)
对于(2),似乎有许多好的、有效的解决方案。rake 任务似乎是一个好方法,并且有一些插件可以使这更容易。只需查看其他一些答案即可了解这些答案的详细信息:)
回答by Aaron Wheeler
Try a rake task. For example:
尝试耙任务。例如:
- Create the file /lib/tasks/bootstrap.rake
- In the file, add a task to create your default user:
- 创建文件/lib/tasks/bootstrap.rake
- 在文件中,添加一个任务来创建您的默认用户:
namespace :bootstrap do
desc "Add the default user"
task :default_user => :environment do
User.create( :name => 'default', :password => 'password' )
end
desc "Create the default comment"
task :default_comment => :environment do
Comment.create( :title => 'Title', :body => 'First post!' )
end
desc "Run all bootstrapping tasks"
task :all => [:default_user, :default_comment]
end
- Then, when you're setting up your app for the first time, you can do rake db:migrate OR rake db:schema:load, and then do rake bootstrap:all.
- 然后,当您第一次设置应用程序时,您可以执行 rake db:migrate 或 rake db:schema:load,然后执行 rake bootstrap:all。
回答by Jason Kim
Use db/seed.rbfound in every Rails application.
使用db/seed.rb在每一个Rails应用程序中。
While some answers given above from 2008can work well, they are pretty outdated and they are not really Rails convention anymore.
虽然上面从2008 年给出的一些答案可以很好地工作,但它们已经过时了,它们不再是真正的 Rails 惯例了。
Populating initial data into database should be done with db/seed.rbfile.
应使用db/seed.rb文件将初始数据填充到数据库中。
It's just works like a Ruby file.
它就像一个 Ruby 文件一样工作。
In order to create and save an object, you can do something like :
为了创建和保存对象,您可以执行以下操作:
User.create(:username => "moot", :description => "king of /b/")
User.create(:username => "moot", :description => "king of /b/")
Once you have this file ready, you can do following
准备好此文件后,您可以执行以下操作
rake db:migrate
rake db:migrate
rake db:seed
rake db:seed
Or in one step
或一步
rake db:setup
rake db:setup
Your database should be populated with whichever objects you wanted to create in seed.rb
您的数据库应该填充您想要在 seed.rb 中创建的任何对象
回答by Jay Stramel
I recommend that you don't insert any newdata in migrations. Instead, only modify existing data in migrations.
我建议您不要在迁移中插入任何新数据。相反,只修改迁移中的现有数据。
For inserting initial data, I recommend you use YML. In every Rails project I setup, I create a fixtures directory under the DB directory. Then I create YML files for the initial data just like YML files are used for the test data. Then I add a new task to load the data from the YML files.
对于插入初始数据,我建议您使用 YML。在我设置的每个 Rails 项目中,我在 DB 目录下创建了一个 fixtures 目录。然后我为初始数据创建 YML 文件,就像 YML 文件用于测试数据一样。然后我添加一个新任务来从 YML 文件加载数据。
lib/tasks/db.rake:
库/任务/db.rake:
namespace :db do
desc "This loads the development data."
task :seed => :environment do
require 'active_record/fixtures'
Dir.glob(RAILS_ROOT + '/db/fixtures/*.yml').each do |file|
base_name = File.basename(file, '.*')
say "Loading #{base_name}..."
Fixtures.create_fixtures('db/fixtures', base_name)
end
end
desc "This drops the db, builds the db, and seeds the data."
task :reseed => [:environment, 'db:reset', 'db:seed']
end
db/fixtures/users.yml:
db/fixtures/users.yml:
test:
customer_id: 1
name: "Test Guy"
email: "[email protected]"
hashed_password: "656fc0b1c1d1681840816c68e1640f640c6ded12"
salt: "188227600.754087929365988"
回答by Jay Stramel
This is my new favorite solution, using the populator and faker gems:
这是我最喜欢的新解决方案,使用 populator 和 faker gems:
回答by DEfusion
回答by Vinko Vrsalovic
I guess the best option is number 3, mainly because that way there will be no default user which is a great way to render otherwise good security useless.
我想最好的选择是数字 3,主要是因为这样就没有默认用户了,这是一种很好的方式,使原本良好的安全性变得毫无用处。
回答by Trevor Stow
Consider using the rails console. Good for one-off admin tasks where it's not worth the effort to set up a script or migration.
考虑使用 rails 控制台。适用于一次性管理任务,在这种情况下,不值得努力设置脚本或迁移。
On your production machine:
在您的生产机器上:
script/console production
... then ...
... 然后 ...
User.create(:name => "Whoever", :password => "whichever")
If you're generating this initial user more than once, then you could also add a script in RAILS_ROOT/script/, and run it from the command line on your production machine, or via a capistrano task.
如果您不止一次生成这个初始用户,那么您还可以在 RAILS_ROOT/script/ 中添加一个脚本,并从生产机器上的命令行或通过 capistrano 任务运行它。
回答by pantulis
That Rake task can be provided by the db-populate plugin:
该 Rake 任务可以由 db-populate 插件提供:
回答by Kevin Davis
Great blog post on this: http://railspikes.com/2008/2/1/loading-seed-data
很棒的博客文章:http: //railspikes.com/2008/2/1/loading-seed-data
I was using Jay's suggestions of a special set of fixtures, but quickly found myself creating data that wouldn't be possible using the models directly (unversioned entries when I was using acts_as_versioned)
我正在使用 Jay 对一组特殊装置的建议,但很快发现自己创建的数据无法直接使用模型(当我使用 act_as_versioned 时未版本化的条目)

