Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails association for two foreign keys for the same table in one table

I am new to RoR and still playing with associations. I need to have two references to a particular model in another model. The scaffolded code doesn't work and I get a "uninitialized constant" error.

Generation commands:

script/generate scaffold BaseModel name:string
script/generate scaffold NewModel name:string base1:references base2:references
db:migrate

Generated models:

class NewModel < ActiveRecord::Base
     belongs_to :base1
     belongs_to :base2
end

and

class BaseModel < ActiveRecord::Base
     has_many :new_models # I added this line
end

When I try to create a new_model at /new_models/new, I tried both the ID and the name of the BaseModel but it does not work. The error I get is:

uninitialized constant NewModel::Base1

I guessed it maps the names, so in my create method, I tried to explicitly set the BaseModel instances:

@new_model = NewModel.new(params[:new_model])
@base1 = BaseModel.find(1) # this exists
@base2 = BaseModel.find(2) # this exists
@new_model.base1 = @base1  # This throws the same error as above

Is there anything I'm missing?

like image 725
Rohit Avatar asked Dec 11 '09 13:12

Rohit


1 Answers

Most of Rails' magic comes from convention over configuration. By naming things according to guidelines Rails can guess at most of the configuration options. ActiveRecord::Associations are no exceptions.

The first argument of any ActiveRecord Association is the name that will be used within the model. This is usually the name of another model, that's the convention. By default class name is the singular of association name in camelcase. The default foreign key in the association is the association name postfixed with "_id". If your association name doesn't match a class name or a foreign key by these patterns you will need to supply them as options.

This will do what you want:

class NewModel
  belongs_to :base1, :class_name => "BaseModel"
  belongs_to :base2, :class_name => "BaseModel"
end

Personally I would give the associations more descriptive names that base1 and base2. Something like this:

Ratings table: id, rater_id, rated_id, rating

class Rating
  belongs_to :rater, :class_name => "User"
  belongs_to :rated_user, :class_name => "User", :foreign_key => "rated_id"
end

A different example could have been used, but this was chosen to highlight when the foreign key option is necessary.

like image 99
MattMcKnight Avatar answered Sep 19 '22 05:09

MattMcKnight