ruby-on-rails - rails : How to populate Db with data without migrations getting in the way?

标签 ruby-on-rails ruby-on-rails-3 activerecord

我的应用程序依赖于数据库 (MySql) 中已有的大约 48,000 行数据。在我看来,使用 ActiveRecord 抽象会带来这样的问题:每次发生迁移时都必须重新插入此数据。情况确实如此吗?或者有解决办法吗?

最佳答案

Ruby on Rails 通过以不同的方式跟踪对应用程序架构所做的更改来处理迁移。这样做的目的是提供一种非常受控的机制来管理数据库的模式和数据。通过在创建初始数据库架构后使用迁移来预填充数据库,此迁移将仅在每个应用程序部署中执行一次。

也许一个示例是说明如何处理 Rails ActiveRecord::Migrations 的最佳方式。您的时间戳显然会有所不同,因此如果您遇到困难,最好手动尝试一下。

$ rails new example -d mysql
$ cd example/
$ rails generate scaffold Users username:string password:string
  invoke  active_record
  create    db/migrate/20111004022310_create_users.rb
  create    app/models/user.rb
  ...
  ...

此迁移创建一个表users,其中包含两个字符串字段 - 用户名和密码。很简单。现在,在此示例中,我假设您已经预先配置了 database.yml

创建数据库、加载架构和初始迁移

$ rake db:setup
/Sites/example/db/schema.rb doesn't exist yet. Run 
"rake db:migrate" to create it then try again. If
you do not intend to use a database, you should
instead alter /Sites/example/config/application.rb
to limit the frameworks that will be loaded

我们仍然需要将初始迁移合并到架构中。这会将用户模型的初始规范加载到数据库架构中,然后可以设置数据库。

$ rake db:migrate
==  CreateUsers: migrating ====================================================
-- create_table(:users)
   -> 0.2389s
==  CreateUsers: migrated (0.2390s) ===========================================
$ rake db:setup
-- create_table("users", {:force=>true})
   -> 0.1460s
-- initialize_schema_migrations_table()
   -> 0.5908s
-- assume_migrated_upto_version(20111004022310, "db/migrate")
   -> 0.0010s

此时,您可以轻松进入rails console并查看初始配置。

$ rails console
ruby-1.9.2-p180 :007 > u = User.new(:username => 'test', :password => 'testing?')
 => #<User id: nil, username: "test", password: "testing?", created_at: nil, updated_at: nil> 
ruby-1.9.2-p180 :008 > u.save!
 => true
ruby-1.9.2-p180 :009 > User.all
 => [#<User id: 2, username: "test", password: "testing?", created_at: "2011-10-04 02:33:56", updated_at: "2011-10-04 02:33:56">] 

预填充数据库

这样您就可以看到初始用户迁移的样子。

$ cat db/migrate/20111004022310_create_users.rb
class CreateUsers < ActiveRecord::Migration
  def self.up
    create_table :users do |t|
      t.string :username
      t.string :password

      t.timestamps
    end
  end

  def self.down
    drop_table :users
  end
end

要填充它,您需要创建一个迁移来充当您的首选数据接口(interface)和 ActiveRecord 之间的代理。如果它位于数据库中的某个位置,我建议使用 FasterCSV 之类的工具将其导入到新迁移的 self.up (或 up)部分。此迁移只会在每个应用程序部署中执行一次,除非您删除数据库并重新开始。

$ rails generate migration prepopulate_users
      invoke  active_record
      create    db/migrate/20111004024648_prepopulate_users.rb
$ cat db/migrate/20111004024648_prepopulate_users.rb 
class PrepopulateUsers < ActiveRecord::Migration
  def self.up
    # Assuming the 'results' is set up as an Enumerable for your data
    results.each do |row|
      u = User.new( :username => row[:username],
                    :password => row[:password] )
      u.save!
    end
  end

  def self.down
  end
end

警告

不过,我要提醒你,你可能会经历很长一段时间(至少一两天)。我已经从运行在完全不同的平台上的旧应用程序中完成了数据的肮脏迁移,您最好希望您的数据集是完美的(并且您已经完美地模仿了数据模型)或者事情将会 中断。

此外,可能存在疏忽

如果我误解了您的问题,并且您希望使用随机数据预填充数据库,您应该看看 Forgery , random-data ,和/或 Faker .

如果我完全偏离主题,请随时发表评论,我会相应地调整我的答案。

关于ruby-on-rails - rails : How to populate Db with data without migrations getting in the way?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7642540/

相关文章:

ruby-on-rails - rails 3.1。使用安全密码在控制台中创建一个用户

activerecord - 在 Rails 3 和 Rspec 中 stub 链式查询

ruby-on-rails - Rails 抛出 Redis::TimeoutError

ruby-on-rails - 截断字符串而不在 Rails 中的单词中间进行切割

ruby-on-rails - 设计——如何用lockable锁定一个账户?

css - Rails 3 CSS 问题

ruby-on-rails - Rails 排序或排序查询很慢

ruby-on-rails - 查看列值是否更新

ruby-on-rails - 模型如何响应方法:find?

ruby-on-rails - 自动编译 Assets 并使用 nginx 提供服务(开发)