162

If I create a new rails 3 migration with (for example)

rails g migration tester title:tester user:references

, everything works fine...however if I add a column with something along the lines of:

rails g migration add_user_to_tester user:references

the reference field is not recognised. In short, the question is: how do I add a referencing column to a rails migration from the command line?

Simone Carletti
  • 164,184
  • 42
  • 341
  • 356
PlankTon
  • 11,872
  • 14
  • 82
  • 144

10 Answers10

205

If you are using the Rails 4.x you can now generate migrations with references, like this:

rails generate migration AddUserRefToProducts user:references

like you can see on rails guides

mrzmyr
  • 5,014
  • 4
  • 28
  • 54
Paulo Fidalgo
  • 19,844
  • 7
  • 85
  • 108
186

EDIT: This is an outdated answer and should not be applied for Rails 4.x+

You don't need to add references when you can use an integer id to your referenced class.

I'd say the advantage of using references instead of a plain integer is that the model will be predefined with belongs_to and since the model is already created and will not be affected when you migrate something existing, the purpose is kind of lost.

So I would do like this instead:

rails g migration add_user_id_to_tester user_id:integer

And then manually add belongs_to :user in the Tester model

dan-klasson
  • 12,215
  • 11
  • 49
  • 91
DanneManne
  • 20,521
  • 5
  • 53
  • 54
  • 9
    But that won't create the appropriate foreign key constraints on databases that support it, right? – abahgat May 02 '11 at 09:02
  • 19
    No, afaik Rails never create foreign key restraints on the database unless you add plugins to do it for you. – DanneManne May 03 '11 at 02:44
  • just studying this post, pls how do i add the reference after all – El nino Jul 19 '12 at 01:31
  • The way I showed does add a reference. But instead of it being a one line generator, it also requires you to add the reference code into your existing model, which is also included in the answer – DanneManne Jul 19 '12 at 06:23
  • 13
    remember to add the index with user:integer:index – rickypai Dec 01 '12 at 17:40
  • This answer is really good, but I'm not sure I understand it fully due to the confusing grammar (multiple 'and' and 'since'. not sure where sentences end and start.) "the model will be predefined with belongs_to and since the model is already created and will not be affected when you migrate something existing, the purpose is kind of lost." – ahnbizcad Apr 25 '14 at 10:27
  • What should i do if the user model is like, `Subscription::User` so how will i write the migration for this? – Alfie Mar 12 '15 at 10:19
  • 3
    Answer is dated, see @Paulo's answer for modern rails. – OneHoopyFrood Mar 30 '15 at 07:30
  • @abahgat with Rails > 4.2 there is now an ```add_foreign_key``` method which facilitates adding a fk constraint at the db level – Drew Aug 19 '15 at 13:25
102

Please note that you will most likely need an index on that column too.

class AddUserReferenceToTester < ActiveRecord::Migration
  def change
    add_column :testers, :user_id, :integer
    add_index  :testers, :user_id
  end
end
Itay Grudev
  • 6,173
  • 4
  • 46
  • 79
Eugene
  • 1,389
  • 1
  • 10
  • 12
  • 1
    Why? Is this true for most belongs_to relationships? – ahnbizcad Apr 25 '14 at 10:30
  • It is indeed for performance reasons and comes in handy if you have a has_many/has_one on the other side of that belongs_to relation. If you are absolutely sure that you will not go through `user.testers` you can omit the index. – Eugene May 09 '14 at 11:19
  • 1
    The `rails g migration ...` generated `add_reference :installs, :device, index: true` which also creates the index. – B Seven Nov 19 '14 at 22:44
49

With the two previous steps stated above, you're still missing the foreign key constraint. This should work:

  class AddUserReferenceToTester < ActiveRecord::Migration
      def change
          add_column :testers, :user_id, :integer, references: :users
      end
  end
35

You can use references in a change migration. This is valid Rails 3.2.13 code:

class AddUserToTester < ActiveRecord::Migration
  def change
    change_table :testers do |t|
      t.references :user, index: true 
    end
  end
  def down
    change_table :testers do |t|
      t.remove :user_id
    end
  end
end

c.f.: http://apidock.com/rails/ActiveRecord/ConnectionAdapters/SchemaStatements/change_table

gl03
  • 967
  • 9
  • 14
27

Running rails g migration AddUserRefToSponsors user:references will generate the following migration:

def change
  add_reference :sponsors, :user, index: true
end
Itay Grudev
  • 6,173
  • 4
  • 46
  • 79
Wirwing
  • 422
  • 6
  • 4
8

When adding a column you need to make that column an integer and if possible stick with rails conventions. So for your case I am assuming you already have a Tester and User models, and testers and users tables.

To add the foreign key you need to create an integer column with the name user_id (convention):

add_column :tester, :user_id, :integer

Then add a belongs_to to the tester model:

class Tester < ActiveRecord::Base
  belongs_to :user
end

And you might also want to add an index for the foreign key (this is something the references already does for you):

add_index :tester, :user_id
Zamith
  • 20,044
  • 2
  • 21
  • 15
8

That will do the trick:

rails g migration add_user_to_tester user_id:integer:index
masterweily
  • 718
  • 6
  • 15
3

You can add references to your model through command line in the following manner:

rails g migration add_column_to_tester user_id:integer

This will generate a migration file like :

class AddColumnToTesters < ActiveRecord::Migration
  def change
    add_column :testers, :user_id, :integer
  end
end

This works fine every time i use it..

Neha
  • 109
  • 6
3

For Rails 4

The generator accepts column type as references (also available as belongs_to).

This migration will create a user_id column and appropriate index:

$ rails g migration AddUserRefToProducts user:references 

generates:

class AddUserRefToProducts < ActiveRecord::Migration
  def change
    add_reference :products, :user, index: true
  end
end

http://guides.rubyonrails.org/active_record_migrations.html#creating-a-standalone-migration

For Rails 3

Helper is called references (also available as belongs_to).

This migration will create a category_id column of the appropriate type. Note that you pass the model name, not the column name. Active Record adds the _id for you.

change_table :products do |t|
  t.references :category
end

If you have polymorphic belongs_to associations then references will add both of the columns required:

change_table :products do |t|
  t.references :attachment, :polymorphic => {:default => 'Photo'}
end

Will add an attachment_id column and a string attachment_type column with a default value of Photo.

http://guides.rubyonrails.org/v3.2.21/migrations.html#creating-a-standalone-migration

shilovk
  • 7,603
  • 15
  • 54
  • 63