In the code below, p.comments.foobar calls #foobar on every comment. Is there a way to call #foobar only on the comments that belong to post "p"?
What you are saying does not make sense to me. p.comments is an array containing the comments that belong to post p. Therefore p.comments.foobar should generate a syntax error as Array does not have a method foobar.
To call foobar on each comment belonging to p do p.comments.each {|c| c.foobar}
Colin
> In the code below, p.comments.foobar calls #foobar on every comment. > Is there a way to call #foobar only on the comments that belong to > post "p"?
> -------------------- > class Comment < ActiveRecord::Base > belongs_to :post
> def self.foobar; end > end
> class Post < ActiveRecord::Base > has_many :comments > end
> p = Post.find_by_id 123 > p.comments.foobar
What you are saying does not make sense to me. p.comments is an array containing the comments that belong to post p. Therefore p.comments.foobar should generate a syntax error as Array does not have a method foobar.
To call foobar on each comment belonging to p do p.comments.each {|c| c.foobar}
Colin
Hi Colin. I agree: an error should occur when calling p.comments.foobar . However, no error occurs.
To use your suggestion:
p.comments.each {|c| c.foobar}
I'll have to change Comment.foobar from a class method to an instance method.
Thanks for your input! Nick
In the code below, p.comments.foobar calls #foobar on every comment. Is there a way to call #foobar only on the comments that belong to post "p"?
-------------------- class Comment < ActiveRecord::Base belongs_to :post
def self.foobar; end end
class Post < ActiveRecord::Base has_many :comments end
p = Post.find_by_id 123 p.comments.foobar
What you are saying does not make sense to me. p.comments is an array containing the comments that belong to post p. Therefore p.comments.foobar should generate a syntax error as Array does not have a method foobar.
Not quite... it looks like an array, but it's not. Otherwise you wouldn't be able to say "p.comments.create(....)" or "p.comments.find(:conditions => ....)" but you can.
The code above works because foobar is defined as class method, not an instance method. Drop that "self." and then your code below is indeed what the grand parent wants.
to be quite precise, if Comment has a class method foo, then calling p.comments.foo calls the foo method, but scoped to those comments with post_id == p.id, so for example if i were to write (contrived example)
class Comment < ... def self.authors find(:all).collect {|comment| comment.author}.uniq end end
then Comment.authors finds you all comment authors, but p.comments.authors finds you every author who has commented on p.
Fred
Thanks Fred that is very helpful. This is one of the constructs in RoR that for a programmer brought up on C is rather difficult to get to grips with as the mechanism by which it works is not obvious, but in practice the result of p.comments.authors is intuitively obvious, so to some extent you just have to grab the ball and run with it.
Colin