在“引用”迁移中指定列名称


124

我想migration在Rails中引用另一个表。通常,我会做类似的事情:

add_column :post, :user, :references

这将创建一个user_idposts表中命名的列。但是,如果user_id我想要而不是类似的东西author_id怎么办?我怎样才能做到这一点?

Answers:


59

手动执行:

add_column :post, :author_id, :integer

但是现在,当您创建belongs_to语句时,您将不得不对其进行修改,因此现在您必须调用

def post
    belongs_to :user, :foreign_key => 'author_id'
end

1
我不必添加任何索引吗?
caarlos0 2012年

1
是的,您需要在迁移中创建索引。
汤姆·哈里森

1
Rails作弊-默认情况下,它实际上并不使用索引。现在,如果您想要索引(这是一个好主意-尽管rails会完全忽略它们),那么肯定可以添加它们。您可能需要查看我链接的指南,以获取有关迁移的一般信息,甚至可能最终将直接调用SQL代码放入迁移中。我会说忽略它,因为它不是Rails的正常部分,您会从中获得0的性能,因为Rails的默认生成的SQL查询没有利用它。 链接
mschultz

嗯了解。非常感谢你!
caarlos0 2012年

使用schema_plusgem,t.references :category, index: true, foreign_key: true, references: :match_categories在迁移文件中也对我有用。
elquimista '16

251

对于Rails 5+

初始定义:

如果您要定义Post模型表格,您可以设置referencesindexforeign_key在一行:

t.references :author, index: true, foreign_key: { to_table: :users }

更新现有:

如果要将引用添加到现有表,则可以执行以下操作:

add_reference :posts, :author, foreign_key: { to_table: :users }

注意: 的默认值为indextrue。


初始定义会允许为空吗?如果不是,您知道可为空的替代方法吗?
Vorpulus Lyphane '17

5
此定义允许nulls。要不允许它们,请添加通常的选项null: false
Ashitaka '17

谢谢。对于“初始定义”,我认为“ index:true”不是必需的。无论有没有,我都会得到相同的架构更改。没关系; 刚看完你的笔记。
乔伊(Joey)

谢谢,这就是我想要的!
Philippe B.

250

Rails 4.2+中,您也可以在db中设置外键这是一个好主意

对于简单的关联,也可以在t.references添加时完成foreign_key: true,但是在这种情况下,您将需要两行。

# The migration
add_reference :posts, :author, index: true
add_foreign_key :posts, :users, column: :author_id

# The model
belongs_to :author, class_name: "User"

2
谢谢,但是这个问题被标记为Rails3,我很高兴为您提供帮助
生态版,

2
哦,我没注意到。好吧,这对我很有帮助。:)
bonh 2016年

2
看到这个,我几乎放弃了希望!谢谢@ecoologic!
丹·威廉姆斯

2
@ecoologic,您可能只想添加一件事,add_foreign_key仅为rails 4.2+。;)
丹·威廉姆斯

4
我不确定您是否需要通话中的references: :users选项add_reference。我没有在文档中看到它的记载,没有它,它似乎可以正常工作。
jakecraige

87

在Rails 4中,使用postgresql和schema_plus gem时,您只需编写

add_reference :posts, :author, references: :users

这将创建一个author_id正确引用的列users(id)

在你的模型中,你写

belongs_to :author, class_name: "User"

注意,在创建新表时,您可以按以下方式编写它:

create_table :things do |t| 
  t.belongs_to :author, references: :users 
end 

注意:schema_plusgem的整体与Rails 5+不兼容,但是此功能由与rails 5兼容的gem schema_auto_foreign_keys(schema_plus的一部分)提供。


28
如果您使用的是create_tablet.references :author, references: :users
Michael Radionov

2
在您的答案中添加@MichaelRadionov的评论将使其变得完美。
toxaq 2015年

2
我一直在查看Rails 4.1的源代码,但找不到任何确实可以:references做任何事情的证据。
jes5199

1
是的,您是对的,我使用schema_plusgem 已有很长时间了,它实际上是在添加该功能。我相应地编辑了答案。
nathanvda

2
在Rails 6中,似乎t.references :col_name, references: other_table_name无需安装额外的gem即可使用该语法。
Qqwy

51

如果您不使用外键,那么另一个表的实际表名则无关紧要。

add_reference :posts, :author

从Rails 5开始,如果您使用外键,则可以在外键选项中指定另一个表的名称。(请参阅https://github.com/rails/rails/issues/21563进行讨论)

add_reference :posts, :author, foreign_key: {to_table: :users}

在Rails 5之前,您应该添加外键作为单独的步骤:

add_foreign_key :posts, :users, column: :author_id

12
to_table是复数形式:{to_table: :users}
hoffmanc

-3

alias_attribute(new_name,old_name)非常方便。只需创建模型和关系即可:

rails g model Post title user:references

然后编辑模型并添加一个属性别名

alias_attribute :author, :user

之后,您将可以运行类似

Post.new(title: 'My beautiful story', author: User.first)

1
当您需要定义对另一个模型的多个引用(例如,帖子(作者,编辑))时
不起作用
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.