如何(以及是否需要)在Rails应用程序中填充最初的数据

65

我有一个Rails应用程序,用户需要登录才能使用。因此,为了使应用程序可用,系统必须有一个初始用户供第一个登录的人使用(然后他们可以创建其他用户)。到目前为止,我已经使用迁移向数据库添加了一个特殊的用户。

在问过这个问题之后,似乎我应该使用db:schema:load而不是运行迁移,在新的开发机器上设置新的数据库。不幸的是,这似乎不包括插入数据的迁移,只包括设置表格、键等的迁移。

我的问题是,如何处理这种情况:

  1. 有没有办法让d:s:l包括插入数据的迁移?
  2. 我是否完全不应该使用迁移以这种方式插入数据?
  3. 我是否根本不应该预先填充数据库中的数据?是否应该更新应用程序代码,以便它优雅地处理没有用户的情况,并允许从应用程序内部实时创建初始用户帐户?
  4. 其他选项?:)
13个回答

45

尝试使用rake任务。例如:

  1. 创建文件/lib/tasks/bootstrap.rake
  2. 在文件中添加任务以创建默认用户:

    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
  1. 第一次设置应用程序时,您可以执行rake db:migrate或rake db:schema:load,然后执行rake bootstrap:all。

如果/lib是只读的,就像在共享托管环境中一样,这个方法就不起作用了。你有没有一个解决方案可以在这种情况下使用? - cbrulak
11
我很确定他在谈论你的应用程序的/lib目录。 - Azeem.Butt

39

在每个Rails应用程序中都可以找到db/seed.rb,请使用它。

虽然上面提供的一些答案来自于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中创建的任何对象。


db:seed 已经为我完成了。 - Krishna Vedula

32

我建议您不要在迁移中插入任何数据。相反,只在迁移中修改现有数据。

对于插入初始数据,我建议使用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"

9

6

尝试使用seed-fu插件,这是一个非常简单的插件,可以帮助您种植数据(并在将来更改该种子数据),还可以让您种植特定于环境的数据和所有环境的数据。


4
我想最好的选择是第三个选项,主要是因为这样就不会有默认用户,这是使本来很好的安全措施变得无效的好方法。

4

我想总结一下我对这个问题的很多好答案,以及现在我已经阅读了它们的想法:

这里有两个不同的问题:

  1. 我应该预先填充数据库我的特殊“管理员”用户吗?还是应用程序提供第一次使用时设置的方法?
  2. 如何预先填充数据库数据?请注意,这是一个有效的问题,无论第1部分的答案如何:预填充有其他用法场景而不仅仅是管理员用户。

对于(1),似乎从应用程序本身设置第一个用户需要相当多的额外工作,而根据定义,这种功能几乎从来不使用。然而,它可能会更安全,因为它强制用户设置他们自己选择的密码。最佳解决方案介于这两个极端之间:编写脚本(或rake任务等)来设置初始用户。然后可以设置脚本在开发期间自动填充默认密码,并要求在生产安装/部署期间输入密码(如果您想防止管理员使用默认密码)。

对于(2),似乎有许多好的有效解决方案。rake任务似乎是一个不错的方式,还有一些插件可以使这更容易。只需查看其他答案的详细信息即可 :)


3

考虑使用Rails控制台。适用于一次性管理任务,不值得设置脚本或迁移的工作。

在您的生产机器上:

script/console production

...然后...

User.create(:name => "Whoever", :password => "whichever")

如果您需要多次生成此初始用户,则可以在RAILS_ROOT/script/中添加脚本,并通过命令行在生产机器上运行它,或通过capistrano任务运行。

3

这篇博客文章讲解了如何加载种子数据:http://railspikes.com/2008/2/1/loading-seed-data

我曾经使用Jay的建议,使用一组特殊的固定数据,但很快发现创建的数据无法直接使用模型(当我使用acts_as_versioned时,版本不兼容)。


3

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接