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

ぐ巨炮叔叔 提交于 2019-12-03 19:13:34

问题


I've discovered a nice way to generate join tables for my HABTM relationships in my Rails app.

rails g migration CreateJoinTable table1 table2

This generates an ActiveRecord::Migration that employs the method create_join_table

I'm wondering what this wonderful mysterious method does. I guess it makes a table (probably without an id field) that has a column for table1 foreign key and a column for table2 foreign key, but does the table have any other features?. My habit for join tables has always been to add a unique index across both those columns so that a relationship between a record in table1 and a record in table2 cannot be entered twice.

My question boils down to: If I use create_join_table do I need to keep adding that unique index, or does this method do that for me (I think it should)?

The documentation I usually look at doesn't go into this sort of detail.


回答1:


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).




回答2:


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.




回答3:


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



回答4:


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


来源:https://stackoverflow.com/questions/32201949/what-is-the-behaviour-of-create-join-table-of-activerecordmigration

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