26

How can I assign different table name with adding foreign key. for e.g

I have a model like

class MyPost < ActiveRecord::Base
  has_many :comments, class_name: PostComment
end

class PostComment < ActiveRecord::Base
  belongs_to :post, class_name: MyPost
end

Now i want to change my migration file like this:

class CreatePostComments < ActiveRecord::Migration
  def change
    create_table :post_comments do |t|
     t.belongs_to :post, index: true
     t.timestamps null: false
    end
    add_foreign_key :post, :class_name => MyPost
  end
end 

But it is not working. Migration is getting cancelled. How do I change my migration file to work with my model structure.

joseramonc
  • 1,811
  • 2
  • 21
  • 40
Braham Shakti
  • 1,408
  • 4
  • 22
  • 39

2 Answers2

48

You can pass in options for the foreign key as following:

class CreatePostComments < ActiveRecord::Migration
  def change
    create_table :post_comments do |t|
      t.references :post, foreign_key: { to_table: :my_posts }, index: true
      t.timestamps null: false
    end
  end
end

This is also true for the index option if you like to add a unique constraint:

t.references :post, foreign_key: { to_table: :my_posts }, index: { unique: true}

By the way, references is an alias for belongs_to, or to be more exact, belongs_to is an alias for references.

See the details in the implementation rails 5.0.rc2 & rails 4.2

ray
  • 5,454
  • 1
  • 18
  • 40
Stefan Staub
  • 689
  • 5
  • 13
  • 7
    `index` is `true` by default. `index: true` is unnecessary. – developer033 Feb 07 '17 at 01:55
  • 8
    [`index` is `true` by default from Rails 5](http://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/SchemaStatements.html#method-i-add_reference). [`index` is `false`by default on previous Rails versions](http://api.rubyonrails.org/v4.2/classes/ActiveRecord/ConnectionAdapters/SchemaStatements.html#method-i-add_reference). – cbliard Jul 20 '17 at 08:25
  • 1
    I'd modify it to `t.references :post, foreign_key: { to_table: :my_posts }, null:false`, cause it won't add `null: false` by default – Alexander Gorg May 12 '20 at 14:34
18

It should look like this:

class CreatePostComments < ActiveRecord::Migration
  def change
    create_table :post_comments do |t|
     t.belongs_to :post, index: true
     t.timestamps null: false
    end
    add_foreign_key :post_comments, :my_posts, column: :post_id
  end
end 

Take a look at the documentation: http://apidock.com/rails/ActiveRecord/ConnectionAdapters/SchemaStatements/add_foreign_key

You use the column option when the column is named differently.

lunr
  • 5,159
  • 4
  • 31
  • 47