0

我正在使用 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 和外键的数据类型是整数,所以如果我试图更改外键整数将它串起来会引发错误。

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

金士顿

4

1 回答 1

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,其方式与通常生成增量整数 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”,但我不知道该怎么做。无论如何,我认为这种方法应该有效。虽然可能有几个错误或位丢失,但这里有点晚了。

于 2013-11-26T20:44:49.167 回答