如何(以及是否)使用初始数据填充 Rails 应用程序
-
09-06-2019 - |
题
我有一个 Rails 应用程序,用户必须登录。因此,为了使应用程序可用,系统中必须有一个初始用户供第一个人登录(然后他们可以创建后续用户)。到目前为止,我已经使用迁移将特殊用户添加到数据库中。
问完后 这个问题, ,看来我应该使用 db:schema:load,而不是运行迁移,在新的开发计算机上设置新的数据库。不幸的是,这似乎不包括插入数据的迁移,只包括那些设置表、键等的迁移。
我的问题是,处理这种情况的最佳方法是什么:
- 有没有办法让 d:s:l 包含数据插入迁移?
- 我不应该使用迁移来以这种方式插入数据吗?
- 我不应该用数据预先填充数据库吗?我是否应该更新应用程序代码,以便它能够优雅地处理没有用户的情况,并允许从应用程序内实时创建初始用户帐户?
- 还有其他选择吗?:)
解决方案 7
我想我应该总结一下我对这个问题的一些很好的答案,以及我自己的想法,现在我已经阅读了它们全部:)
这里有两个不同的问题:
- 我应该使用特殊的“管理员”用户预先填充数据库吗?或者应用程序是否应该提供一种在首次使用时进行设置的方法?
- 如何用数据预先填充数据库?请注意,无论第 1 部分的答案如何,这都是一个有效的问题:除了管理员用户之外,还有其他预填充的使用场景。
对于 (1),从应用程序本身内部设置第一个用户似乎是相当多的额外工作,因为根据定义,该功能几乎从未使用过。然而,它可能会稍微安全一些,因为它强制用户设置自己选择的密码。最好的解决方案是在这两个极端之间:有一个脚本(或 rake 任务,或其他)来设置初始用户。然后可以将脚本设置为在开发期间自动填充默认密码,并要求在生产安装/部署期间输入密码(如果您不希望管理员使用默认密码)。
对于(2),似乎有许多好的、有效的解决方案。rake 任务似乎是一个好方法,并且有一些插件可以使这变得更加容易。只需查看其他一些答案即可了解其中的详细信息:)
其他提示
尝试一下 rake 任务。例如:
- 创建文件 /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
- 然后,当您第一次设置应用程序时,可以执行 rake db:migrate 或 rake db:schema:load,然后执行 rake bootstrap:all。
使用 db/seed.rb
每个 Rails 应用程序中都可以找到。
虽然上面给出了一些答案 2008 可以很好地工作,但它们已经过时了,并且不再是真正的 Rails 约定。
将初始数据填充到数据库中应该完成 db/seed.rb
文件。
它就像 Ruby 文件一样工作。
为了创建和保存对象,您可以执行以下操作:
User.create(:username => "moot", :description => "king of /b/")
准备好该文件后,您可以执行以下操作
rake db:migrate
rake db:seed
或者一步到位
rake db:setup
您的数据库应该填充您想要在 Seed.rb 中创建的任何对象
我建议您不要插入任何 新的 迁移中的数据。相反,仅修改迁移中的现有数据。
为了插入初始数据,我建议您使用 YML。在我设置的每个Rails 项目中,我都会在DB 目录下创建一个fixtures 目录。然后,我为初始数据创建 YML 文件,就像 YML 文件用于测试数据一样。然后我添加一个新任务来从 YML 文件加载数据。
lib/tasks/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:
test:
customer_id: 1
name: "Test Guy"
email: "test@example.com"
hashed_password: "656fc0b1c1d1681840816c68e1640f640c6ded12"
salt: "188227600.754087929365988"
这是我最喜欢的新解决方案,使用 populator 和 faker gems:
尝试一下 种子富 插件是一个非常简单的插件,允许您播种数据(并在将来更改种子数据),还可以让您播种特定于环境的数据和所有环境的数据。
我猜最好的选择是数字 3,主要是因为这样就没有默认用户,这是使其他良好的安全性变得无用的好方法。
考虑使用 Rails 控制台。适合一次性管理任务,不值得花费精力设置脚本或迁移。
在您的生产机器上:
script/console production
...然后 ...
User.create(:name => "Whoever", :password => "whichever")
如果您多次生成此初始用户,那么您还可以在 RAILS_ROOT/script/ 中添加一个脚本,并从生产计算机上的命令行或通过 capistrano 任务运行它。
该 Rake 任务可以由 db-populate 插件提供:
关于此的精彩博客文章:http://railspikes.com/2008/2/1/loading-seed-data
我正在使用 Jay 的一组特殊装置的建议,但很快发现自己创建了直接使用模型无法实现的数据(当我使用acts_as_versioned 时,未版本化的条目)
我会把它保留在迁移中。虽然建议使用该架构进行初始设置,但这样做的原因是它速度更快,从而避免出现问题。对数据进行一次额外的迁移应该没问题。
您还可以将数据添加到架构文件中,因为它的格式与迁移相同。你只会失去自动生成功能。
对于用户和组,应根据应用程序的需求而不是编程的意外情况来定义现有用户的问题。也许您的应用程序需要管理员;然后预填充。或者也许不是 - 然后添加代码以在应用程序启动时优雅地请求用户设置。
关于更普遍的问题,很明显许多 Rails 应用程序可以从预先填充的日期中受益。例如,美国地址持有应用程序也可能包含所有州及其缩写。我相信,对于这些情况,迁移是你的朋友。
有些答案已经过时了。从 Rails 2.3.4 开始,有一个名为 Seed 的简单功能 db/seed.rb
:
#db/seed.rb
User.create( :name => 'default', :password => 'password' )
Comment.create( :title => 'Title', :body => 'First post!' )
它提供了一个新的 rake 任务,您可以在迁移后使用该任务来加载数据:
rake db:seed
Seed.rb 是一个经典的 Ruby 文件,可以随意使用任何经典的数据结构(数组、哈希等)和迭代器来添加数据:
["bryan", "bill", "tom"].each do |name|
User.create(:name => name, :password => "password")
end
如果您想添加带有 UTF-8 字符的数据(在法语、西班牙语、德语等中很常见),请不要忘记在文件开头添加:
# ruby encoding: utf-8
这个 Railscast 是一个很好的介绍: http://railscasts.com/episodes/179-seed-data