Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding a Model Reference to existing Rails model

I'd like to know the "proper" way to approach adding a relation between two existing classes in Rails 3.

Given existing models: Clown & Rabbit

I'd like to add a reference (belongs_to) from Rabbit to Clown. I start by trying to generate a migration:

rails g migration AddClownToRabbits clown:reference

which gives me a migration that looks like:

class AddClownToRabbits < ActiveRecord::Migration
  def self.up
    add_column :rabbits, :clown, :reference
  end

  def self.down
    remove_column :rabbits, :clown
  end
end

After rake db:migrate on this migration I examine SQLite3's development.db and see a new column: "clown" reference

I guess I was expecting a "clown_id" integer column and a migration that looked like:

class AddClownToRabbits < ActiveRecord::Migration
  def self.up
    add_column :rabbits, :clown_id
  end

  def self.down
    remove_column :rabbits, :clown_id
  end
end

I'm sure :reference is supposed to be equivalent to "t.references :clown" but I can't find the documentation (big surprise). API says add_column: Instantiates a new column for the table. The type parameter is normally one of the migrations native types, which is one of the following: :primary_key, :string, :text, :integer, :float, :decimal, :datetime, :timestamp, :time, :date, :binary, :boolean.

...with no reference to :reference.

like image 695
Meltemi Avatar asked Dec 02 '10 19:12

Meltemi


People also ask

How do I add a reference to an existing table in rails?

When you already have users and uploads tables and wish to add a new relationship between them. Then, run the migration using rake db:migrate . This migration will take care of adding a new column named user_id to uploads table (referencing id column in users table), PLUS it will also add an index on the new column.


3 Answers

If you are using edge rails (4.0) you can use:

rails generate migration AddAddressRefToContacts address:references

As you can see by the docs.

like image 185
Paulo Fidalgo Avatar answered Oct 04 '22 21:10

Paulo Fidalgo


After you set belongs_to in Rabbit, and has_many in Clown, you can do a migration with:

add_column :rabbit, :clown_id, :integer

EDIT: See Paulo's answer below for a more updated answer (Rails 4+)

like image 35
clemensp Avatar answered Oct 04 '22 20:10

clemensp


I'm not sure where you got this idea, but there is no (and never has been) such syntax to do what you want with add_column. To get the behavior you want, you'd have to do t.refences :clown, as you stated. In the background this will call: @base.add_column(@table_name, "#{col}_id", :integer, options).

See here.

EDIT:

I think I can see the source of your confusion. You saw the method call t.reference and assumed it was a datatype because calls such as t.integer and t.string exist, and those are datatypes. That's wrong. Reference isn't a datatype, it's just simply the name of a method, similar to t.rename is.

like image 43
ryeguy Avatar answered Oct 04 '22 21:10

ryeguy