将postgresql数据库迁移到uuid rails 3.1

时间:2013-10-25 13:25:38

标签: ruby-on-rails ruby-on-rails-3.1 uuid

我正在使用rails 3.1和ruby 1.9.3,现在我想在rails 3中使用uuid概念 所以我喜欢: -

create_table :posts, :id => false do |t|
 t.string :uuid, :limit => 36, :primary => true
end

ActiveRecord::Base.class_eval do
 set_primary_key 'uuid'
 before_create :generate_uuid
 def generate_uuid
 self.id = UUIDTools::UUID.random_create.to_s
 end
end

这适用于新数据,现在我想用关系迁移现有数据。因为uuid他们使用数据类型作为字符串,在postgresql中用于primary_key和外键的数据类型是整数,所以如果我想改变字符串的外键整数是抛出错误。

请你告诉我一些例子,如何做到这一点。

kingston.s

1 个答案:

答案 0 :(得分:2)

首先,要在ActiveRecord中使用UUID,您需要启用uuid-ossp扩展。创建一个新的迁移。

class EnableUuidOssp < ActiveRecord::Migration
  def change
    enable_extension 'uuid-ossp'
  end
end

其次,您不需要在迁移中使用字符串类型,而是存在uuid类型。创建新表时:

create_table :posts, id: :uuid do |t|
end

这将自动生成UUID,其方式与通常生成增量Integer ID的方式相同。如果要将UUID字段添加到现有表中:

change_table :posts do |t|
  t.uuid :uuid, default: 'uuid_generate_v4()'
end

默认值:'uuid_generate_v4()'将确保Postgres为您生成新的UUID。

第三,要实际迁移现有数据,我猜你需要创建迁移,1)向所有模型添加UUID字段2)创建新的UUID外键3)使用UUID外键关联模型4)删除旧外键5)重命名新外键:

class AddUuidToPosts < ActiveRecord::Migration
  def change
    change_table :posts do |t|
      t.uuid :uuid, default: 'uuid_generate_v4()'
    end
  end
end

# assuming you have a comments table that belongs to posts
class AddUuidToComments < ActiveRecord::Migration
  def change
    change_table :comments do |t|
      t.uuid :uuid, default: 'uuid_generate_v4()'
    end
  end
end

class AssociateCommentsWithPostings < ActiveRecord::Migration
  def change
    # Add a uuid_posting_id field to comments relate comments to postings
    # through the posting UUID
    change_table :comments do |t|
      t.uuid :uuid_posting_id
    end

    # Loop through all existing postings and update all associated comments
    # new foreign key field
    Posting.all.each do |posting|
      # Not sure about this, but you might need to touch the posting to generate
      # a UUID
      posting.touch 

      Comment.where(posting_id: posting.id).
        update_all(uuid_posting_id: posting.uuid)
    end

    remove_column :comments, :posting_id
    rename_column :comments, :uuid_posting_id, :posting_id
  end
end

# You don't need to override ActiveRecord::Base to set the primary key to :uuid.
# Only do this in existing models that you migrated to UUIDs. In any new tables
# that you create, the id column will be a UUID, as long as you use the migration
# format that I showed you at the top.
class Posting < ActiveRecord::Base
  set_primary_key :uuid
end

你应该加倍努力,实际上删除旧的整数id字段并将新的UUID id重命名为“id”,但我不知道如何做到这一点。无论如何,我认为这种方法应该有效。可能会有一些错误或缺失,但这里有点晚了。