I got some Manager
and SoccerTeam
model. A manager "owns" many soccer teams; also a manager can comment on soccer teams and can comment on other managers too:
manager.rb
# Soccer teams the manager owns
has_many :soccer_teams, :dependent => :restrict
# Comments the manager has made on soccer teams or other managers
has_many :reviews, :class_name => "Comment", :foreign_key => :author_id, :dependent => :destroy
# Comments the manager has received by other managers
has_many :comments, :as => :commentable, :dependent => :destroy
# Soccer teams that have received a comment by the manager
has_many :observed_teams, :through => :comments, :source => :commentable, :source_type => "SoccerTeam"
soccer_team.rb
# The manager that owns the team
belongs_to :manager
# Comments received by managers
has_many :comments, :as => :commentable, :dependent => :destroy
# Managers that have reviewed the team
has_many :observers, :through => :comments, :source => :author, :class_name => "Manager"
comment.rb
belongs_to :commentable, :polymorphic => true
belongs_to :author, :class_name => Manager
Now, if I have a Manager commenting on a SoccerTeam I expect to find:
Comment
object in manager.reviews
and in soccer_team.comments
SoccerTeam
object in manager.observed_teams
Manager
object in soccer_team.observers
While everything works well for the first and the third point, when I call manager.observed_teams
I always obtain an empty array. To actually obtain the list of soccer teams a manager has commented on I need to use:
manager.reviews.collect{ |review| Kernel.const_get(review.commentable_type).find(review.commentable_id) if review.commentable_type == "SoccerTeam" }
Which is ugly. I expect the simple manager.observed_teams
to work… why it doesn't?
Edit
I went a step further in understanding why it does not work. In fact, the genrated SQL is:
SELECT "soccer_teams".* FROM "soccer_teams" INNER JOIN "comments" ON "soccer_teams".id = "soccer_teams".commentable_id AND "comments".commentable_type = 'SoccerTeam' WHERE (("comments".commentable_id = 1) AND ("comments".commentable_type = 'Manager'))
While I want it to be:
SELECT "soccer_teams".* FROM "soccer_teams" INNER JOIN "comments" ON "soccer_teams".id = "comments".commentable_id AND "comments".commentable_type = 'SoccerTeam' WHERE ("comments".author_id = 1)
So the question is simple: how to obtain that query? (An heuristic attempt with :foreign_key
ans :as
, as expected, hasn't solved the problem!).
I think you've simply used the wrong association for observed_teams
. Instead of
has_many :observed_teams, :through => :comments,
:source => :commentable, :source_type => "SoccerTeam"
Try this:
has_many :observed_teams, :through => :reviews,
:source => :commentable, :source_type => "SoccerTeam"
Also in,
has_many :reviews, :class_name => :comment,
:foreign_key => :author_id, :dependent => :destroy
:comment
should be 'Comment'
and in
has_many :comments, :as => commentable, :dependent => :destroy
commmentable
should be :commmentable
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With