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