在Rails 4中添加参考列迁移


310

用户有很多上传。我想在uploads表中添加引用的列user。迁移应该是什么样?

这就是我所拥有的。我不确定我应该使用(1):user_id, :int还是(2):user, :references。我什至不确定(2)是否有效。只是尝试以“轨道”方式进行操作。

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

除Rails 3外的相关问题。Rails 3迁移:是否添加参考列?

Answers:


706

Rails 4.x

当您已经有 users and uploads表并希望在它们之间添加新的关系时

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

rails g migration AddUserToUploads user:references

它将创建一个迁移文件为:

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

然后,使用运行迁移rake db:migrate。这种迁移会照顾添加一个名为新列user_iduploads表(引用idusers表),再加上它也将在新列中添加索引。

更新[用于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

这会将新的外键添加到表的user_id列中uploads。键引用表中的idusers

注意:这是添加引用的补充,因此您仍然需要先创建引用,然后再创建外键您可以选择在同一迁移或单独的迁移文件中创建外键)。Active Record仅支持单列外键,当前仅支持mysqlmysql2并且PostgreSQL支持适配器。不要在其他适配器(例如sqlite3,等等)上尝试此操作。请参考《Rails指南:外键》。


8
在许多情况下,也最好添加外键。add_foreign_key(Rails 4.2)
poerror 2015年

18
我相信您可以在一行中完成所有操作:add_reference:uploads,:user,index:true,foreign_key:true @KirtiThorat
user1801879 2015年

32
现在,如果您使用特殊的生成器语法进行迁移,Rails 4.2将自动创建包含外键约束的正确迁移。rails g migration AddUserToUploads user:references产生add_reference :uploads, :user, index: true, foreign_key: true适当的迁移。
jrhorn424

10
使用...index: true, foreign_key: true代替邻线add_foreign_key
华盛顿Botelho,2015年

2
为什么我们同时需要foreign_keyt.referencet.reference本质上不等于foriegn_key+ index吗?
geoboy

187

滑轨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


2
对于以名称分隔的类,请使用like Local::User而不是User执行like rails g migration AddLocalUserToUploads user:references
嘉莫

3
这会自动添加:index
吗?

4
@Zeke是的,运行迁移并检查您的架构,它应该说类似t.index ["user_id"], name: "index_uploads_on_user_id", using: :btree
Mirror318 '16

1
是的,当我在迁移中手动添加add_index时,出现“索引存在”错误:P @ Mirror318
Saravanabalagi Ramachandran,

2
我们还应该添加belongs_to :userUpload类,所以我们可以使用upload.user来获取用户实例。
机智

17

如果您喜欢使用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

9

[使用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

1
该答案似乎与@ Mirror318的答案重复。如果您认为其中缺少某些内容,请在上面的答案中发表评论。谢谢。
哈比卜


7

只是记录是否有人遇到相同的问题...

在我的情况我一直在使用:uuid领域,上述答案没有工作,我的情况下,由于导轨5使用创建一列:bigint,而不是:uuid

add_column :uploads, :user_id, :uuid
add_index :uploads, :user_id
add_foreign_key :uploads, :users

这也更清楚了发生了什么。但是,是的,UUID现在应该是标准的。
hadees

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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.