65

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

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

我的问题是,处理这种情况的最佳方法是什么:

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

13 回答 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 OR rake db:schema:load,然后执行 rake bootstrap:all。
于 2008-09-15T12:52:12.730 回答
37

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 中创建的任何对象

于 2013-02-13T22:01:48.670 回答
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"
于 2008-09-15T17:14:16.737 回答
9

这是我最喜欢的新解决方案,使用 populator 和 faker gems:

http://railscasts.com/episodes/126-populating-a-database

于 2008-09-16T12:37:43.413 回答
6

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

于 2008-09-16T09:17:04.143 回答
4

我想最好的选择是 3 号,主要是因为这样不会有默认用户,这是一种很好的方式来使原本好的安全性变得无用。

于 2008-09-15T11:36:20.120 回答
4

我想我会总结一下我对这个问题的一些很好的答案,连同我自己的想法,现在我已经全部阅读了:)

这里有两个不同的问题:

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

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

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

于 2008-09-16T19:42:43.517 回答
3

考虑使用 rails 控制台。适合一次性的管理任务,不值得努力设置脚本或迁移。

在您的生产机器上:

script/console production

... 然后 ...

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

如果您不止一次地生成此初始用户,那么您还可以在 RAILS_ROOT/script/ 中添加一个脚本,并从生产机器上的命令行或通过 capistrano 任务运行它。

于 2008-09-15T12:04:04.877 回答
3

该 Rake 任务可以由 db-populate 插件提供:

http://github.com/joshknowles/db-populate/tree/master

于 2008-09-15T21:04:17.930 回答
3

很棒的博客文章: http ://railspikes.com/2008/2/1/loading-seed-data

我正在使用 Jay 对一组特殊装置的建议,但很快发现自己创建了无法直接使用模型的数据(我使用acts_as_versioned 时的未版本化条目)

于 2010-09-10T03:48:40.327 回答
2

我会把它保留在迁移中。虽然建议使用架构进行初始设置,但这样做的原因是它更快,从而避免了问题。对数据进行一次额外的迁移应该没问题。

您还可以将数据添加到架构文件中,因为它的格式与迁移相同。您只会失去自动生成功能。

于 2008-09-15T11:33:31.813 回答
2

对于用户和组,应根据应用程序的需求而不是编程的偶然性来定义预先存在的用户的问题。也许您的应用需要管理员;然后预填充。或者可能不是 - 然后添加代码以在应用程序启动时优雅地请求用户设置。

关于更一般的问题,很明显许多 Rails 应用程序可以从预填充日期中受益。例如,美国地址持有申请也可能包含所有州及其缩写。对于这些情况,我相信迁移是你的朋友。

于 2008-09-15T17:00:58.797 回答
1

有些答案已经过时了。从 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

于 2014-01-21T11:08:32.643 回答