在“引用”迁移中指定列名
Posted
技术标签:
【中文标题】在“引用”迁移中指定列名【英文标题】:Specifying column name in a "references" migration 【发布时间】:2012-11-21 14:12:23 【问题描述】:我想在 Rails 中创建一个migration
,引用另一个表。通常,我会这样做:
add_column :post, :user, :references
这会在posts
表中创建一个名为user_id
的列。但是,如果我想要author_id
之类的东西而不是user_id
,该怎么办?我该怎么做?
【问题讨论】:
【参考方案1】:在 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_plus
gem 整体上与 rails 5+ 不兼容,但此功能由与 rails 5 兼容的 gem schema_auto_foreign_keys(schema_plus 的一部分)提供。
【讨论】:
如果您使用的是create_table
:t.references :author, references: :users
将@MichaelRadionov 的评论添加到您的答案中会更完美。
我一直在查看 Rails 4.1 源代码,但找不到任何证据表明 :references
确实做了任何事情。
是的,你是对的,我使用schema_plus
gem 已经很久了,它实际上是在添加这个功能。我相应地编辑了我的答案。
在 Rails 6 中,t.references :col_name, references: other_table_name
语法似乎可以在不安装额外 gem 的情况下工作。【参考方案2】:
在Rails 4.2+中,您还可以在数据库中设置foreign keyswhich is a great idea。
对于简单的关联,这也可以在 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"
【讨论】:
谢谢,但问题标记为 Rails3,我很乐意提供帮助 哦,我没注意到。嗯,这对我很有帮助。 :) 当我看到这个时,我几乎要放弃希望了!谢谢@ecoologic! @ecoologic,您可能想要添加的只是一件事,add_foreign_key 仅是 rails 4.2+。 ;) 我不确定您是否需要add_reference
调用中的 references: :users
选项。我没有在文档中看到它的记录,如果没有它,它似乎对我有用。【参考方案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)
【讨论】:
这在您需要定义对另一个模型的多个引用时不起作用,例如,post (author, editor)【参考方案4】:适用于 Rails 5+
初始定义:
如果你定义你的Post
模型表,你可以在一行中设置references
、index
和foreign_key
:
t.references :author, index: true, foreign_key: to_table: :users
更新现有:
如果您要添加对现有表的引用,您可以这样做:
add_reference :posts, :author, foreign_key: to_table: :users
注意: index
的默认值为 true。
【讨论】:
初始定义是否允许空值?如果没有,你知道可以为空的替代方案吗? 这个定义允许null
s。要不允许它们,请添加常用选项 null: false
。
谢谢。对于“初始定义”,我认为“索引:真”不是必需的。无论有没有它,我都会得到相同的架构更改。没关系;刚刚在最后看到了你的笔记。
谢谢,这就是我要找的!【参考方案5】:
如果您不使用外键,那么另一个表的实际表名是什么并不重要。
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
【讨论】:
请注意rails g migration AddAuthorToPosts author:references
不能输出这个。您必须手动更新迁移(请参阅:github.com/rails/rails/blob/main/railties/lib/rails/generators/…)【参考方案6】:
手动操作:
add_column :post, :author_id, :integer
但是现在,当你创建belongs_to语句时,你必须修改它,所以现在你必须调用
def post
belongs_to :user, :foreign_key => 'author_id'
end
【讨论】:
我不需要添加任何索引吗? 是的,您需要在迁移中创建索引。 Rails 作弊 - 默认情况下它并不真正使用索引。现在,如果您想要索引(这是一个好主意 - 尽管 Rails 会完全忽略它们),那么您当然可以添加它们。您将需要查看我链接的指南以获取有关迁移的更多信息,您甚至可能最终将调用 SQL 代码直接放在迁移中。我想说忽略它,因为它不是 rails 的正常部分,你会得到 0 的性能,因为 rails 的默认生成的 SQL 查询没有利用它。 link 嗯明白了。非常感谢! 使用schema_plus
gem,t.references :category, index: true, foreign_key: true, references: :match_categories
在迁移文件中也为我工作。以上是关于在“引用”迁移中指定列名的主要内容,如果未能解决你的问题,请参考以下文章