在Rails中,我如何创建一个迁移,以更改我的主键类型?

4

我正在使用Rails 4.2.7和PostGres。我创建了几个表,这些表都有数字主键。以下是我一个Rails迁移的示例:

class CreateMyObjects < ActiveRecord::Migration
  def change
    create_table :my_objects do |t|
      t.string :name
      t.date :day
      t.references :user, index: true, foreign_key: true

      t.timestamps null: false
    end
  end
end

我这个表里面没有任何数据,但是我有几个表通过外键与它链接。我想将主键从数字更改为GUID(UUID),因为我将会有一个情况,即在两个不同的数据库中创建数据,当我合并数据时,我不希望出现主键冲突。如何创建一个迁移来更改主键类型为我的UUID类型,并如何更新所有链接到该表的外键?
谢谢-Dave

说实话,这是我主张在更新时放弃外键的一个案例。 - Ven
我不理解你的评论,请举个例子。 - Dave
暂时移除外键,以便在事务中违反完整性。 - Ven
我该如何开始执行迁移呢? - Dave
你没有解释清楚。我们如何在本地复现它? - user1735921
想象一下,我有一个带有数字主键的表格,我想将主键类型更改为UUID。我该怎么做? - Dave
1个回答

5
class ChangePrimaryKey < ActiveRecord::Migration
  def change
    remove_column :my_objects, :id # remove existing primary key
    add_column    :my_objects, :uuid, :string
    execute "ALTER TABLE my_objects ADD PRIMARY KEY (uuid);"
  end
end

class MyObject < ActiveRecord::Base
  self.primary_key = :uuid
end

关于自增 - Rails 不会自动为你递增字符串类型的 id,所以你需要自己处理。
你可以在模型中使用 before_create 回调函数:
before_create :generate_uuid

  private

  def generate_uuid
    loop do
      self.uuid = SecureRandom.base64(16)         # or other way to generate uniq string
      break unless self.class.find_by(uuid: uuid) # make sure you don't repeat the uuid
    end
  end

您还可以向主键列添加约束,例如 not null 约束、uniqueness 约束、length 等


谢谢,但这并没有涉及到那些有外键指向这个表的表。实际上,当我运行这个迁移时,我会得到错误提示:“PG::DependentObjectsStillExist: ERROR: 无法删除 my_objects 表的 id 列,因为其他对象依赖于它,详细信息:user_my_objects 表上的约束 fk_rails_27b0854e5e 依赖于 races 表的 id 列”。 - Dave
@Dave 这是一个特殊情况。您需要创建一个迁移,将从关联表对象中删除 foreign_key,然后执行我的答案中的迁移,最后通过新的外键添加关联(在新的迁移中)。 - Andrey Deineko
我该如何创建这样的迁移?另外,您将主键列命名为uuid。我能否将其保留为“id”以符合惯例? - Dave
@Dave 当然,你可以随意命名。请提供与 my_objects 表相关联的表格,并定义关联 - 我会尝试编写迁移。 - Andrey Deineko
很棒,我找到了一些执行迁移的代码。最后一个问题,当ID字段是整数时,它是否会自动填充?这仍然会发生吗?那肯定是以前的好处之一--不必管理ID的值。 - Dave
@Dave,不幸的是你必须自己管理它,但是好消息是,这很容易,可以看一下更新后的答案。 - Andrey Deineko

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接