Double Secret Edit: I was answering another question and came across something that should work for you. It's a bit of a crazy hack involving the Thread.current global hash. And probably not advised at all, but it works.
It involves creating a second has_many votes association on Comments
class Comment < ActiveRecord::Base
has_many :votes
belongs_to :post
has_many :current_user_votes, :class_name => "Vote",
:conditions => '`#{Vote.table_name}`.user_id = \
#{Thread.current[:current_user].id}'
end
It also requires you to set Thread.current[:current_user] = current_user in the controller where you're going to be calling these methods.
Then you should be able to do
@post.comments.find(:all, :include => :current_user_votes)
To get a list of comments, that have eager loaded only the :current_user_votes. All in one query. If you're getting multiple posts at once, you can do this.
Post.find(:all, :include => { :comments => :current_user_votes},
:conditions => ...)
Which will populate a list of posts, and eager load their comments which in turn will each have their current_user_votes eager loaded.
Original Answer (preserved for posterity)
I don't think it's possible to select all of one model eager load only the relevant associations in one query.
The best you're going to get is pretty much what you've done. Select all of one model and then for each them load only the relevant association with a named scope or finder.
This statement that doesn't work is only selecting comments the user has voted on.
@post.comments.all(:joins => :votes,
:conditions => ['votes.user_id = ?', current_user.id])
This statement selects the same set of comments, but also eager loads all votes for the comments it selects.
@post.comments.all(:include => :votes,
:conditions => ['votes.user_id = ?', current_user.id])
Really what you're going to have to do is call rated_by? on each comment. You might be able to minimize database impact by using a named scope. But I honestly don't think it's going to make an improvement.
If you're so worried about hitting the database so hard you could do something like this:
class Post < ActiveRecord::Base
has_many :comments
has_many :votes, :through => :comments
...
end
class Vote < ActiveRecord::Base
belongs_to :comments
...
named_scope :made_by_user, lambda {|user|
{:conditions => {:user_id => user}}
}
end
@users_votes = @post.votes.made_by_use(current_user)
@comments = @post.comments.find(:all, :include => :votes)
@comments.each{|comment|
user_voted_this_on_this_comment = comment.votes & @user_votes
...
}
Honestly I don't think it's worth the effort.
P.S. There's a Ruby convention regarding methods names that end in a question mark should always return a boolean value.