# AR inheritance and class methods

**URL:** <https://www.ruby-forum.com/t/ar-inheritance-and-class-methods/171136>\
**Category:** Rails\
**Created:** [June 26, 2009, 9:45pm UTC](https://www.ruby-forum.com/t/ar-inheritance-and-class-methods/171136 "2009-06-26T21:45:02Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![nickh](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/7ea924/32.png) [@nickh](https://www.ruby-forum.com/u/nickh)\
**Post date:** [June 26, 2009, 9:45pm UTC](https://www.ruby-forum.com/t/ar-inheritance-and-class-methods/171136/1 "2009-06-26T21:45:02Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![nickh](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/7ea924/32.png) [@nickh](https://www.ruby-forum.com/u/nickh)\
**Post date:** [June 26, 2009, 9:57pm UTC](https://www.ruby-forum.com/t/ar-inheritance-and-class-methods/171136/2 "2009-06-26T21:57:56Z")

</div>

2009/6/26 Nick H. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> 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

---

<div class="post-metadata">

**Author:** ![nickh](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/7ea924/32.png) [@nickh](https://www.ruby-forum.com/u/nickh)\
**Post date:** [June 26, 2009, 10:16pm UTC](https://www.ruby-forum.com/t/ar-inheritance-and-class-methods/171136/3 "2009-06-26T22:16:05Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![nickh](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/7ea924/32.png) [@nickh](https://www.ruby-forum.com/u/nickh)\
**Post date:** [June 26, 2009, 10:16pm UTC](https://www.ruby-forum.com/t/ar-inheritance-and-class-methods/171136/4 "2009-06-26T22:16:05Z")

</div>

On Jun 26, 3:51 pm, Colin L. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) 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

---

<div class="post-metadata">

**Author:** ![nickh](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/7ea924/32.png) [@nickh](https://www.ruby-forum.com/u/nickh)\
**Post date:** [June 27, 2009, 8:34am UTC](https://www.ruby-forum.com/t/ar-inheritance-and-class-methods/171136/5 "2009-06-27T08:34:17Z")

</div>

2009/6/26 Frederick C. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

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

---

<div class="post-metadata">

**Author:** ![nickh](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/7ea924/32.png) [@nickh](https://www.ruby-forum.com/u/nickh)\
**Post date:** [June 26, 2009, 11:46pm UTC](https://www.ruby-forum.com/t/ar-inheritance-and-class-methods/171136/6 "2009-06-26T23:46:10Z")

</div>

On Jun 26, 9:10 pm, Philip H. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) 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
