views:

52

answers:

2

Expanding on recent_posts_on_self below, I want to add an all_recent_posts_on_self method but I'm not sure if it's possible using the syntax self.posts.find. On the other hand, all_recent_posts_on_class seems straightforward.

class User < ActiveRecord::Base
  has_many :posts, :class_name => "Post" , :foreign_key => "author_id"
  has_many :comments, :class_name => "Comment", :foreign_key => "author_id"

  def recent_posts_on_class
    Post.find(  :all, :conditions => ['author_id = ?', self.id],
                :order => 'created_at asc', :limit => 5)
  end

  def recent_posts_on_self
    self.posts.find(:all, :order => 'created_at ASC', :limit => 5)
  end
end

In the example above, I have two ways of finding the recent blog posts that are associated with a user. I can call Post.find and pass it the author_id or I can call self.posts.find and I don't need to pass an author id. I assume this is because in the latter case, self.posts has already been limited based on the primary key of the user object and the has_many :posts associated with this user. This is an advantage in this case because I don't need to go to the trouble of passing author_id as an argument. But if I did not need to limit the query by author, would it be possible to create an all_recent_posts_on_self to do this?

What I'm talking about is an equivalent of this method (which omits the :conditions):

  def all_recent_posts_on_class
    Post.find(:all, :order => 'created_at asc', :limit => 5)
  end

But using self.posts.find instead of Post.find:

  def all_recent_posts_on_self
    self.posts.find(...)
  end

Also:

Even if it's possible to use self.posts.find to do this, is it "better" to use Post.find?

+1  A: 

I'm not sure why you would want to use self.posts.find(..) to look for posts from other authors. This idiom is specifically for the purpose of finding a subset of the objects associated with the particular instance.

Post.find() is what you should use when you do not want limit to a particular User model. After all, the posts() method on the User object was merely a convenience that is effectively the same as (a cached) call to Post.find(:all, :conditions => ['author_id', self.id]).

fd
Ok, I accept your logic as to why it makes sense to use Post.find() to look for posts from other authors. But is it even *possible* to look for posts from other authors through self.posts.find()?
pez_dispenser
Not possible. Anything you do will just AND the query segments together. So you'll have "AND author_id = 5 AND author_id = 6". That's not likely to give you anything, unless you're using a RDMS I haven't heard of. :)
Ian Terrell
So that's how it works!
pez_dispenser
+4  A: 

This isn't exactly what you asked, but I consider this helpful to know and following common patterns helps avoid complicated or confusing implementations.

The "Rails way" to do this is to use named scopes:

class Post < ActiveRecord::Base
  belongs_to :user
  named_scope :recent, :order => 'created_at desc', :limit => 5
end

class User < ActiveRecord::Base
  has_many :posts
end

It doesn't get much more declarative and easy to read than this:

user.posts.recent # 5 most recent posts by the user
Post.recent # 5 most recent posts globally
Ian Terrell
That's really nice. Didn't know you could do that. Thanks.
pez_dispenser