ActiveRecord::Migration 的 create_join_table 的行为是啥?
Posted
技术标签:
【中文标题】ActiveRecord::Migration 的 create_join_table 的行为是啥?【英文标题】:What is the behaviour of create_join_table of ActiveRecord::Migration?ActiveRecord::Migration 的 create_join_table 的行为是什么? 【发布时间】:2015-11-19 00:52:28 【问题描述】:我发现了一种在我的 Rails 应用程序中为我的 HABTM 关系生成连接表的好方法。
rails g migration CreateJoinTable table1 table2
这会生成一个使用create_join_table
方法的ActiveRecord::Migration
我想知道这个奇妙的神秘方法有什么作用。我猜它创建了一个表(可能没有id
字段),其中包含 table1 外键列和 table2 外键列,但是该表还有其他功能吗?我对连接表的习惯一直是在这两个列中添加唯一索引,这样 table1 中的记录和 table2 中的记录之间的关系就不能输入两次。
我的问题归结为:如果我使用create_join_table
,我是否需要继续添加该唯一索引,或者这种方法是否对我这样做(我认为应该这样做)?
documentation I usually look at 没有涉及到这种细节。
【问题讨论】:
【参考方案1】:还要注意如何定义此连接表的依赖销毁。
如果您稍后离开 HABTM 并使用 through:
定义关系并弄错了,您可能会遇到我报告的 here 的“to_sym”错误。
确保你已经像这样定义了销毁:
class Proposal < ActiveRecord::Base
has_many :assignments
has_many :products, through: :assignments, dependent: :destroy # <- HERE
end
class Product < ActiveRecord::Base
has_many :assignments
has_many :proposals, through: :assignments, dependent: :destroy # <- HERE
end
class Assignment < ActiveRecord::Base
belongs_to :product
belongs_to :proposal
end
不是这个:
class Proposal < ActiveRecord::Base
has_many :assignments, dependent: :destroy
has_many :products, through: :assignments
end
class Product < ActiveRecord::Base
has_many :assignments, dependent: :destroy
has_many :proposals, through: :assignments
end
class Assignment < ActiveRecord::Base
belongs_to :product
belongs_to :proposal
end
【讨论】:
当你把:destroy
声明放在:through
关系上时,会不会破坏对应的Product
s或Proposal
s而不仅仅是Assignment
?
@Toby1Kenobi 嗯,这是个好问题。不知道,需要测试一下。【参考方案2】:
在没有任何块的情况下调用,create_join_table
只是创建一个表,其中两个外键引用两个连接的表。
但是,当您调用该方法执行任何其他操作(例如,添加索引)时,您实际上可以传递一个块。来自 Rails 文档:
create_join_table :products, :categories do |t|
t.index :product_id
t.index :category_id
end
看看create_join_table
documentation。
您可以查看底部的create_join_table
代码(点击Source: show)。
【讨论】:
【参考方案3】:SchemaStatements#create_join_table() 只创建没有任何花哨索引等的连接表,...因此,如果您希望在两个字段上使用唯一性约束,您必须执行以下操作:
class CreateJoinTable < ActiveRecord::Migration
def change
create_join_table :posts, :users do |t|
t.integer :post_id, index: true
t.integer :user_id, index: true
t.index [:post_id, :user_id], name: 'post_user_un', unique: true
end
end
end
请注意
create_join_table
默认不会创建id
字段。
【讨论】:
【参考方案4】:事实证明,它只做我在问题中描述的基础知识。我只是通过运行迁移并查看db/schema.rb
中的结果来发现这一点
对于那些感兴趣的人,要获得唯一索引,请执行以下操作:
class CreateJoinTable < ActiveRecord::Migration
def change
create_join_table :posts, :users
add_index :posts_users, [:post_id, :user_id], unique: true, name: 'index_posts_users'
end
end
【讨论】:
以上是关于ActiveRecord::Migration 的 create_join_table 的行为是啥?的主要内容,如果未能解决你的问题,请参考以下文章