# Trying to Wrap My Head Around HM:t and HABTM w/ a Sample App

**URL:** <https://www.ruby-forum.com/t/trying-to-wrap-my-head-around-hm-t-and-habtm-w-a-sample-app/160200>\
**Category:** Rails\
**Created:** [February 12, 2009, 9:11pm UTC](https://www.ruby-forum.com/t/trying-to-wrap-my-head-around-hm-t-and-habtm-w-a-sample-app/160200 "2009-02-12T21:11:38Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![spammy](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/22d042/32.png) [@spammy](https://www.ruby-forum.com/u/spammy)\
**Post date:** [February 12, 2009, 9:11pm UTC](https://www.ruby-forum.com/t/trying-to-wrap-my-head-around-hm-t-and-habtm-w-a-sample-app/160200/1 "2009-02-12T21:11:38Z")

</div>

I am cheap and in an attempt to learn about rails & relationships I’m  
trying to create an application that my friends and I can use as a way  
to split the cost of items we buy @ Costco.

Right now the models i have are:

User - Various people involved  
Run - Represents Costco runs  
Item - Individual items purchased during a Costco run

I was hoping that someone could point me in the right direction as to  
how i setup up the relationships…

These are my models:

Item.rb

# An item is purchased on a run and it’s cost can be split between many

Users. Because many Users can split the cost of an Item, it is owned by  
1 or more Users.  
belongs\_to :run  
belongs\_to :user

Run.rb

# A run is an individual trip to costco. On a run many items are

purchased.  
has\_many :items

User.rb

# A User can participate in many runs and during the run will be buying

Items (or maybe buying a fraction of 1 item).  
has\_many :runs  
has\_many :items, :through =\> :participations #This is my area of  
question

I realize this is incorrect as is, but could someone shed some light on  
how i should be thinking about a situation like this?

Thanks for your time and for reading a big post like this 😉

---

<div class="post-metadata">

**Author:** ![spammy](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/22d042/32.png) [@spammy](https://www.ruby-forum.com/u/spammy)\
**Post date:** [February 13, 2009, 4:37pm UTC](https://www.ruby-forum.com/t/trying-to-wrap-my-head-around-hm-t-and-habtm-w-a-sample-app/160200/2 "2009-02-13T16:37:59Z")

</div>

On Feb 13, 10:23 am, Marnen Laibow-Koser [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> On Feb 12, 3:11 pm, Josh T. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
> wrote:  
> […]
> 
> > User.rb
> > 
> > # A User can participate in many runs and during the run will be buying
> > 
> > Items (or maybe buying a fraction of 1 item).  
> > has\_many :runs  
> > has\_many :items, :through =\> :participations #This is my area of  
> > question
> 
> Why do you need a :through at all here? has\_many :items should be  
> sufficient, if I understand the situation correctly.  
> […]

Aack! Right after posting that, I realized something else. If a User  
can participate in many Runs, and a Run can have many Users associated  
with it, then you need

class Run  
has\_and\_belongs\_to\_many :users  
end

class User  
has\_and\_belongs\_to\_many :runs  
end

That will create a join table (called runs\_users) associating Users  
with Runs. The join table will not be able to hold any additional  
information, and will not be associated with an ActiveRecord model  
type. If you need the join to hold additional information or be an  
ActiveRecord subclass, that’s what has\_many :through is for.

In other words, has\_and\_belongs\_to\_many is kind of a special case of  
the simplest type of has\_many :through.

Does that help?

## Best,

Marnen Laibow-Koser  
removed\_email\_address@domain.invalid  
[http://www.marnen.org](http://www.marnen.org)

---

<div class="post-metadata">

**Author:** ![spammy](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/22d042/32.png) [@spammy](https://www.ruby-forum.com/u/spammy)\
**Post date:** [February 13, 2009, 5:49pm UTC](https://www.ruby-forum.com/t/trying-to-wrap-my-head-around-hm-t-and-habtm-w-a-sample-app/160200/3 "2009-02-13T17:49:15Z")

</div>

On Feb 13, 10:30 am, Marnen Laibow-Koser [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:  
[…]

> class Run  
> has\_and\_belongs\_to\_many :users  
> end
> 
> class User  
> has\_and\_belongs\_to\_many :runs  
> end
> 
> That will create a join table (called runs\_users) associating Users  
> with Runs.  
> […]

Again with the posting too quickly…I made a silly error in this  
description. Of course this won’t _create_ a join table, but it will  
expect one in the database as I described. Sorry about my incoherence  
this morning.

## Best,

Marnen Laibow-Koser  
marnen@marnenorg  
[http://www.marnen.org](http://www.marnen.org)

---

<div class="post-metadata">

**Author:** ![spammy](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/22d042/32.png) [@spammy](https://www.ruby-forum.com/u/spammy)\
**Post date:** [February 13, 2009, 4:25pm UTC](https://www.ruby-forum.com/t/trying-to-wrap-my-head-around-hm-t-and-habtm-w-a-sample-app/160200/4 "2009-02-13T16:25:33Z")

</div>

On Feb 12, 3:11 pm, Josh T. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:  
[…]

> belongs\_to :user  
> This looks fine.

> Run.rb
> 
> # A run is an individual trip to costco. On a run many items are
> 
> purchased.  
> has\_many :items

So does this. At some point, you might also need has\_many :users; it  
depends on what you’re doing.

> User.rb
> 
> # A User can participate in many runs and during the run will be buying
> 
> Items (or maybe buying a fraction of 1 item).  
> has\_many :runs  
> has\_many :items, :through =\> :participations #This is my area of  
> question

Why do you need a :through at all here? has\_many :items should be  
sufficient, if I understand the situation correctly.

> I realize this is incorrect as is, but could someone shed some light on  
> how i should be thinking about a situation like this?
> 
> Thanks for your time and for reading a big post like this 😉

You’re welcome!

## Best,

Marnen Laibow-Koser  
removed\_email\_address@domain.invalid  
[http://www.marnen.org](http://www.marnen.org)

---

<div class="post-metadata">

**Author:** ![spammy](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/22d042/32.png) [@spammy](https://www.ruby-forum.com/u/spammy)\
**Post date:** [February 13, 2009, 6:52pm UTC](https://www.ruby-forum.com/t/trying-to-wrap-my-head-around-hm-t-and-habtm-w-a-sample-app/160200/5 "2009-02-13T18:52:08Z")

</div>

What about something like (not real code, just trying to convey the  
idea):

Item (id, name)

# an item is an item. given that you’ll probably

# purchase the same item more than once, you could

# generate an Item list as a shopping list for your

# next Costco binge

has\_many purchases

Purchase (id, item\_id, run\_id, amount)

# on a run, you bought some item that cost some

# amount, and someone’s gonna pay

belongs\_to item  
belongs\_to run  
has\_many shares

Run (id, datetime?)

# on this particular run, someone made some number of

# purchases (User seems incidental to a run, important

# only through its participation in shares)

has\_many purchases

Share (id, user\_id, purchase\_id, percent)

# the cost of each purchase can be divided between

# one or more users

belongs\_to user  
belongs\_to purchase

User(id, name)

# each user can participate in any number of runs, and

# would thereby be liable for some shares

has\_many shares

---

<div class="post-metadata">

**Author:** ![spammy](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/22d042/32.png) [@spammy](https://www.ruby-forum.com/u/spammy)\
**Post date:** [February 15, 2009, 10:11pm UTC](https://www.ruby-forum.com/t/trying-to-wrap-my-head-around-hm-t-and-habtm-w-a-sample-app/160200/6 "2009-02-15T22:11:15Z")

</div>

Maybe this is a stupid follow up question, but could :through somehow  
apply to this scenario?

---

<div class="post-metadata">

**Author:** ![spammy](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/22d042/32.png) [@spammy](https://www.ruby-forum.com/u/spammy)\
**Post date:** [February 15, 2009, 10:02pm UTC](https://www.ruby-forum.com/t/trying-to-wrap-my-head-around-hm-t-and-habtm-w-a-sample-app/160200/7 "2009-02-15T22:02:48Z")

</div>

Hi Ar Chron and Marnen Laibow-Koser,

Thanks a lot for responding. Both of your posts have helped me quite a  
bit.

I think i need to go in the direction of Ar’s response though because it  
seems a bit more robust. Especially considering the introduction of the  
“Share” model as this will allow me to divide things up between Users  
using different %s per user.

You do sometimes run into situations where people want to split things  
in unequal percents – ie 24 box of Snickers; user1 takes 6 snickers,  
user2 takes 6 snickers, and user3 gets 12 snickers and diabetes.

I will give this a go and if it turns out half descent put it on github  
or something for other people who pride themselves on being cheap heheh

🙂
