在 Rails 4 中添加引用列迁移

Posted

技术标签:

【中文标题】在 Rails 4 中添加引用列迁移【英文标题】:Add a reference column migration in Rails 4 【发布时间】:2014-05-13 22:42:34 【问题描述】:

一个用户有很多上传。我想在引用useruploads 表中添加一列。迁移应该是什么样子?

这就是我所拥有的。我不确定是否应该使用 (1) :user_id, :int 或 (2) :user, :references。我什至不确定(2)是否有效。只是想以“rails”的方式做到这一点。

class AddUserToUploads < ActiveRecord::Migration
  def change
    add_column :uploads, :user_id, :integer
  end
end

Rails 3 以外的相关问题。Rails 3 migrations: Adding reference column?

【问题讨论】:

【参考方案1】:

只是为了记录是否有人有同样的问题......

在我的情况下,我一直在使用 :uuid 字段,而上述答案不适用于我的情况,因为 rails 5 正在使用 :bigint 而不是 :uuid 创建列:

add_reference :uploads, :user, index: true, type: :uuid

参考:Active Record Postgresql UUID

【讨论】:

发生了什么也更清楚了。但是,是的,UUID 现在应该是标准的了。【参考方案2】:

创建迁移文件

rails generate migration add_references_to_uploads user:references

默认外键名

这将在上传表中创建一个 user_id 列作为外键

class AddReferencesToUploads < ActiveRecord::Migration[5.2]
  def change
    add_reference :uploads, :user, foreign_key: true
  end
end

用户模型:

class User < ApplicationRecord
  has_many :uploads
end

上传模型:

class Upload < ApplicationRecord
  belongs_to :user
end

自定义外键名:

add_reference :uploads, :author, references: :user, foreign_key: true

这将在上传表中创建一个 author_id 列作为外键。

用户模型:

class User < ApplicationRecord
  has_many :uploads, foreign_key: 'author_id'
end

上传模型:

class Upload < ApplicationRecord
  belongs_to :user
end

【讨论】:

如何指定一个字段用作外键?假设我想使用唯一的字符串字段而不是行 ID 作为外键。迁移语法如何? 如果我理解正确,您想使用行 ID 以外的字段。 add_foreign_key :from_table, :to_table, column: :field primary_key: "row_id" 出于性能原因,您可能还想对其进行索引【参考方案3】:

如果您喜欢 updown 方法的另一种替代方法,请尝试以下方法:

  def up
    change_table :uploads do |t|
      t.references :user, index: true
    end
  end

  def down
    change_table :uploads do |t|
      t.remove_references :user, index: true
    end
  end

【讨论】:

【参考方案4】:

[使用 Rails 5]

生成迁移:

rails generate migration add_user_reference_to_uploads user:references

这将创建迁移文件:

class AddUserReferenceToUploads < ActiveRecord::Migration[5.1]
  def change
    add_reference :uploads, :user, foreign_key: true
  end
end

现在,如果您观察架构文件,您将看到上传表包含一个新字段。类似:t.bigint "user_id"t.integer "user_id"

迁移数据库:

rails db:migrate

【讨论】:

这个答案似乎与@Mirror318 的答案重复。如果您认为其中缺少某些内容,请对上述答案发表评论。谢谢。【参考方案5】:

做同样事情的另一种语法是:

rails g migration AddUserToUpload user:belongs_to

【讨论】:

【参考方案6】:

Rails 4.x

当您已有 usersuploads 表并希望在它们之间添加新关系

您需要做的就是:使用以下命令生成迁移:

rails g migration AddUserToUploads user:references

这将创建一个迁移文件:

class AddUserToUploads < ActiveRecord::Migration
  def change
    add_reference :uploads, :user, index: true
  end
end

然后,使用 rake db:migrate 运行迁移。 此迁移将负责将名为 user_id 的新列添加到 uploads 表(引用 users 表中的 id 列),此外它还将在新列上添加索引。

更新 [适用于 Rails 4.2]

不能信任 Rails 来保持引用完整性; 关系数据库在这里为我们提供了帮助。这意味着我们可以在数据库级别本身添加外键约束,并确保数据库将拒绝任何违反此集合引用完整性的操作。正如@infoget 评论的那样,Rails 4.2 提供了对外键(参照完整性) 的原生支持。这不是必需的,但您可能希望将外键(因为它非常有用)添加到我们在上面创建的引用中。

要将外键添加到现有引用,请创建一个新迁移以添加外键:

class AddForeignKeyToUploads < ActiveRecord::Migration
  def change
    add_foreign_key :uploads, :users
  end
end

要创建一个完全带有外键的全新引用(在 Rails 4.2 中),请使用以下命令生成迁移:

rails g migration AddUserToUploads user:references

这将创建一个迁移文件:

class AddUserToUploads < ActiveRecord::Migration
  def change
    add_reference :uploads, :user, index: true
    add_foreign_key :uploads, :users
  end
end

这将为uploads 表的user_id 列添加一个新的外键。键引用users 表中的id 列。

注意:这是除了添加引用之外,因此您仍然需要先创建引用,然后创建外键您可以选择创建外键键入相同的迁移或单独的迁移文件)。 Active Record 仅支持单列外键,目前仅支持 mysqlmysql2PostgreSQL 适配器。不要尝试与sqlite3 等其他适配器一起使用。请参阅Rails Guides: Foreign Keys 以供参考。

【讨论】:

在许多情况下,添加外键也很好。 add_foreign_key (Rails 4.2) 我相信您可以在一行中完成所有操作:add_reference :uploads, :user, index: true, foreign_key: true @KirtiThorat 现在,如果您使用特殊的生成器语法进行迁移,Rails 4.2 将自动创建包含外键约束的正确迁移。 rails g migration AddUserToUploads user:references 在适当的迁移中产生 add_reference :uploads, :user, index: true, foreign_key: true 使用...index: true, foreign_key: true 代替行add_foreign_key 为什么我们需要foreign_keyt.referencet.reference本质上不等于foriegn_key + index吗?【参考方案7】:

导轨 5

您仍然可以使用此命令来创建迁移:

rails g migration AddUserToUploads user:references

迁移看起来与以前有些不同,但仍然有效:

class AddUserToUploads < ActiveRecord::Migration[5.0]
  def change
    add_reference :uploads, :user, foreign_key: true
  end
end

注意是:user,而不是:user_id

【讨论】:

对于命名空间类,例如 Local::User 而不是 User 执行类似 rails g migration AddLocalUserToUploads user:references 的操作。 这会自动添加:index @Zeke 是的,运行迁移并检查您的架构,它应该说类似于t.index ["user_id"], name: "index_uploads_on_user_id", using: :btree 是的,当我在迁移中手动添加 add_index 时出现“索引存在”错误:P @Mirror318 我们还应该在Upload类中添加belongs_to :user,这样我们就可以使用upload.user来获取用户实例。

以上是关于在 Rails 4 中添加引用列迁移的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Rails 迁移中添加检查约束?

Rails 3 迁移:添加参考列?

Rails 5:为啥即使我删除了迁移文件,rails 也会向 schema.rb 添加列

添加带有rails迁移错误的整数数组列

Ruby on Rails:如何使用迁移向现有列添加非空约束?

Rails迁移以将主键添加到现有表