访问Rails迁移的原始ActiveRecord数据

时间:2014-02-19 20:09:36

标签: sql ruby-on-rails ruby activerecord

我想将用户表的某些列迁移到单独的相关表中。其中一些列使用ActiveRecord的serialize功能将哈希值和数据集存储在一列中。

class User < ActiveRecord::Base
  ...
  serialize :foo, Hash
  ...
end

我想将该列(除了许多其他列)移到一个单独的表中:

class Profile < ActiveRecord::Base
  ...
  serialize :foo, Hash

  belongs_to :user
  ...
end

作为迁移的一部分,我在删除用户列之前将一堆用户属性复制到配置文件中。问题是,当我读user.foo时,数据不再反序列化。因此,当我设置profile.foo = user.foo时,我收到错误:Attribute was supposed to be a Hash, but was a String

有没有办法在迁移过程中复制原始数据库值,还是在这种情况下是否需要执行自己的反序列化?

谢谢!

编辑:添加迁移

class CreateProfile < ActiveRecord::Migration
  def up
    create_table :profiles do |t|
      t.integer :user_id
      t.text :foo

      # A bunch of other fields
    end

    User.all.find_each do |user|
      params = { user: user }

      # Copy all fields here
      params[:foo] = user[:foo]
      ...

      profile = Profile.new(params)
      profile.save!
    end

    # Remove a bunch of fields
    remove_column :users, :foo
    ...
  end

  ...
end

2 个答案:

答案 0 :(得分:2)

您可以在迁移中执行原始sql,如果您有大量用户记录,这将是最快的

execute("INSERT INTO profiles(user_id, foo) SELECT id, foo FROM users")

答案 1 :(得分:1)

您似乎要删除serialize :foo, Hash模型中的User行,预计此列将被删除。因此,您遇到了所描述的问题。你可以:

  • 保留该行,并在所有迁移运行后稍后将其删除。这意味着 所有现有环境的所有迁移代码库(或者它们将在@scttnlsn指出后突破)。一个更简单的方法是......

  • 使用SQL'UPDATE'语句复制数据:

假设您事先创建了个人资料,您可以像这样更新:

execute("UPDATE profiles SET foo = users.foo FROM users WHERE user_id = users.id")

如果您在此迁移过程中动态创建这些配置文件记录,请使用类似于@Vimsha建议的INSERT查询。