AR inheritance and class methods

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

Thanks,
Nick

2009/6/26 Nick H. [email protected]:

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

end
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.

On Jun 26, 3:51 pm, Colin L. [email protected] wrote:

end
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

2009/6/26 Frederick C. [email protected]:

what the grand parent wants.
end

then Comment.authors finds you all comment authors, but
p.comments.authors finds you every author who has commented on p.

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

On Jun 26, 9:10 pm, Philip H. [email protected] wrote:

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