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

两盒软妹~` 提交于 2019-11-30 09:06:57
Yanis Vieilly

Called without any block, create_join_table just creates a table with two foreign keys referring to the two joined tables.

However, you can actually pass a block when you call the method to do any additional operations (say, adding indexes for example). From the Rails doc:

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

Have a look at create_join_table documentation.

You can check the create_join_table code at the bottom (click on Source: show).

SchemaStatements#create_join_table() only creates join table without any fancy indexes etc,... So if you wish to use uniqueness constraint on two fields you have to do something like this:

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.

It turns out it doesn't do any more than the basics I described in the question. I found this out simply by running the migration and seeing what ends up in db/schema.rb

For those interested, to get the unique index do this:

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

Also be aware of how you define the dependent destroy for this join table.

If you later move away from HABTM and define the relationships using through: and get it wrong you might run into the 'to_sym' error I reported here.

Make sure you have defined the destroy like this:

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

not this:

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
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!