I'm trying to find the 10 most recent comments on photos so I can integrate them into an activity feed on my Rails 3.0.3 application.
I've got a Photo model, which inherits from an Upload model using single table inheritance:
class Upload < ActiveRecord::Base
...
end
class Photo < Upload
has_many :comments, :as => :commentable
...
end
The polymorphic association commentable is described in the Comment model:
class Comment < ActiveRecord::Base
belongs_to :commentable, :polymorphic => true
end
So far so good, right? The problem comes when I try to construct a query. After some trial and error, I came up with this code that sits in the Photo model:
def self.latest_comments(count = 10)
Comment.where(:commentable_type => "Upload")\
.joins("INNER JOIN uploads ON comments.commentable_id = uploads.id")\
.where("uploads.type" => "Photo").order("comments.created_at DESC").limit(count)
end
This code works on my development machine with SQLite, but I've had to make some changes to get it to work on the production server using PostgreSQL. The above incarnation of the query hasn't been tested on the production server yet, but I was looking for a cleaner way of structuring the query, as the above doesn't feel very robust, nor does it seem very 'Railsy'.
What I'd like is to be able to say is
Comment.joins(:commentable => :photo)
...but this raises an exception, presumably because Rails doesn't know how to do the join:
ActiveRecord::EagerLoadPolymorphicError: Can not eagerly load the polymorphic association :commentable
I came upon a post on StackOverflow that described a different way of querying a polymorphic association. I was able to come up with the following code based upon this post:
Comment.find_all_by_commentable_type("Upload", :include => :commentable,
:order => "created_at DESC", :limit => 10)
However, this doesn't work for STI: since Photo is inheriting from Upload, I can't directly fetch the comments pertaining to photos - only the comments for all classes inheriting from Upload.
I've looked at a fair number of other posts relating to either polymorphism or STI, but none combine the two in the way I'm looking for. I could just muddle around with the initial query, but does anyone have any thoughts on alternative ways to structure a query involving polymorphism and STI?
Edit: I found another question on here along the same lines as mine. Unfortunately, the top answer didn't provide the solution I'm looking for. If I were to apply it to my problem I'd be moving the has_many :comments
association from the Photo
model to the Upload
model, and adding some code to the Comment class to determine the correct class of commentable
. This isn't ideal as it breaks the modelling in that any subclass of Upload will have comments. There must be a better way...?
Upload
is given the associationhas_many :comments
, but I don't want to break my model by doing this. If I don't want to disrupt my model in that way, is what I want to achieve actually possible without a long chained query, I wonder? – Vaudevillian