Reputation: 3773
Given that I have following structure:
class A < ActiveRecord::Base
has_and_belongs_to_many :bs, :class_name => "B", :join_table => "ab"
end
class AB < ActiveRecord::Base
#ab has a date column "creation_date"
#ab also has a text column "creatior"
end
class B < ActiveRecord::Base
end
I successfully retrieve "creation_date" attribute in rails console
console> A.find(1).bs.first.creation_date
=> "14/08/1874"
In controller
@a = A.find(1)
@bs = a.bs
But using it in a view (partial), I got following error
bs.each do |b|
b.b_attribute #this is O.K.
b.creation_date # cause error => undefined method `creation_date` for #<B:...>
end
# also try to debug in partial
A.find(1).bs.first.creation_date #=> this return data correctly
The problem as shown above, what can possibly cause undefined method
whilst the direct attributes are still accessible.
Anyone have any idea what is wrong with my code?
Upvotes: 1
Views: 535
Reputation:
When you're dealing with an intermediate model, you shouldn't use has_and_belongs_to_many
. That method works only when the join table is not a model. You need to make a clear distinction between the concepts of a model and a table. In rails, you rarely have access to the underlying table, most often you deal with the wrapping models.
If your join table has anything more than the foreign keys to A
and B
, and you need to access that additional data, then it needs to be a model. In your case, it is, but you're not using the correct relation. It should look like this:
class A < ActiveRecord::Base
has_many :abs
has_many :bs, :through => :abs
end
class AB < ActiveRecord::Base
end
class B < ActiveRecord::Base
end
Afterwards, accessing creation_date
and creator
should be done through the AB
model, since it really is an attribute that belongs to it.
Take a look here for a quick explanation with examples: http://guides.rubyonrails.org/association_basics.html#choosing-between-has_many-through-and-has_and_belongs_to_many
Upvotes: 2