ActiveRecord::Migration 的 create_join_table 的行为是什么?

What is the behaviour of create_join_table of ActiveRecord::Migration?

我发现了一种在我的 Rails 应用程序中为我的 HABTM 关系生成连接 table 的好方法。

rails g migration CreateJoinTable table1 table2

这会生成一个 ActiveRecord::Migration,它使用 create_join_table

方法

我想知道这个神奇的神秘方法有什么作用。我猜它会生成一个 table(可能没有 id 字段),其中有一列用于 table1 外键,一列用于 table2 外键,但是table 还有其他功能吗?。我对 join tables 的习惯一直是在这两个列之间添加一个唯一索引,这样 table1 中的记录和 table2 中的记录之间的关系就不会被输入两次.

我的问题归结为:如果我使用 create_join_table,我是否需要继续添加该唯一索引,或者这种方法是否为我做(我认为应该)?

documentation I usually look at 没有涉及这种细节。

事实证明,它除了我在问题中描述的基础知识外,并没有做更多的事情。我只是通过 运行 迁移并查看 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

在没有任何块的情况下调用,create_join_table 只是创建一个 table,其中有两个外键引用两个连接的 tables。

但是,当您调用该方法执行任何其他操作(例如,添加索引)时,您实际上可以传递一个块。来自 Rails 文档:

create_join_table :products, :categories do |t|
  t.index :product_id
  t.index :category_id
end

看看create_join_table documentation

您可以查看底部的create_join_table代码(点击来源:显示)。

SchemaStatements#create_join_table() 只创建连接 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

Please also note that create_join_table by default does NOT create id field.

还要注意如何为此连接定义依赖销毁 table。

如果您稍后离开 HABTM 并使用 through: 定义关系并且弄错了,您可能 运行 进入我报告的 'to_sym' 错误 here

确保你已经像这样定义了销毁:

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