# Has\_many option explanation

**URL:** <https://www.ruby-forum.com/t/has-many-option-explanation/143524>\
**Category:** Rails\
**Created:** [July 19, 2008, 11:14pm UTC](https://www.ruby-forum.com/t/has-many-option-explanation/143524 "2008-07-19T23:14:14Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![bruparel](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/e47774/32.png) [@bruparel](https://www.ruby-forum.com/u/bruparel)\
**Post date:** [July 19, 2008, 11:14pm UTC](https://www.ruby-forum.com/t/has-many-option-explanation/143524/1 "2008-07-19T23:14:14Z")

</div>

I am maintaining an application that has an account model which has many  
payments. So the account model has a has\_many relationship as shown  
below:

class Account \< ActiveRecord::Base  
…  
has\_many :payments, :order =\> “created\_at ASC” do  
def charge(amount, paying\_for)  
Payment.charge(proxy\_owner, amount, paying\_for)  
end

```
def commit(action, amount, paying_for)
  Payment.commit(proxy_owner, action, amount, paying_for)
end

def gift(days = nil)
  Payment.gift(proxy_owner, days)
end

```

end  
…  
end

This may be an RoR 101 question, but why would someone define methods in  
a has\_many block? Can’t this be simply called as:

account\_inst.payments.charge(amount, paying\_for) for example?

I do not understand what is the benefit of defining (or proxying ) class  
methods belonging to the many side of this relationship in this manner?

Thanks for your time.

Bharat

---

<div class="post-metadata">

**Author:** ![bruparel](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/e47774/32.png) [@bruparel](https://www.ruby-forum.com/u/bruparel)\
**Post date:** [July 20, 2008, 12:14pm UTC](https://www.ruby-forum.com/t/has-many-option-explanation/143524/2 "2008-07-20T12:14:34Z")

</div>

On Jul 19, 10:14 pm, Bharat R. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> This may be an RoR 101 question, but why would someone define methods in  
> a has\_many block? Can’t this be simply called as:

It’s nicer to write some\_account.payments.gift than it is to write  
Payment.gift(some\_account). You get the association scoping for free  
which can help you avoid mistakes and make things more readable.

> account\_inst.payments.charge(amount, paying\_for) for example?

That is precisely what the association extension methods that have  
been defined allow you to do.  
One trick that is not well known enough is that if foo is a class  
method on payments then you can call  
account\_inst.payments.foo() and it will call the class method foo  
except that everything will be scoped to only act on those payments  
belong to foo. This won’t work with the existing charge method since  
it requires an account as its first parameter.

Fred

> I do not understand what is the benefit of defining (or proxying ) class  
> methods belonging to the many side of this relationship in this manner?

---

<div class="post-metadata">

**Author:** ![bruparel](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/e47774/32.png) [@bruparel](https://www.ruby-forum.com/u/bruparel)\
**Post date:** [July 20, 2008, 6:36pm UTC](https://www.ruby-forum.com/t/has-many-option-explanation/143524/3 "2008-07-20T18:36:28Z")

</div>

Thanks Fred. You wrote:

“This won’t work with the existing charge method since  
it requires an account as its first parameter.”

Was this an oversight since the first parameter of the existing charge  
method is amount as shown below?

def charge(amount, paying\_for)  
Payment.charge(proxy\_owner, amount, paying\_for)  
end

Nice explanation.

Regards,

Bharat

---

<div class="post-metadata">

**Author:** ![bruparel](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/e47774/32.png) [@bruparel](https://www.ruby-forum.com/u/bruparel)\
**Post date:** [July 20, 2008, 7:38pm UTC](https://www.ruby-forum.com/t/has-many-option-explanation/143524/4 "2008-07-20T19:38:05Z")

</div>

On 20 Jul 2008, at 17:35, Bharat wrote:

> Thanks Fred. You wrote:
> 
> “This won’t work with the existing charge method since  
> it requires an account as its first parameter.”
> 
> Was this an oversight since the first parameter of the existing charge  
> method is amount as shown below?

No - what i meant that the charge method you would get for free on the  
payments association (because of the existence of Payment.charge)  
wouldn’t do the write thing.

Fred
