# Model Madness: habtm vs through

**URL:** <https://www.ruby-forum.com/t/model-madness-habtm-vs-through/60919>\
**Category:** Rails\
**Created:** [May 18, 2006, 4:34pm UTC](https://www.ruby-forum.com/t/model-madness-habtm-vs-through/60919 "2006-05-18T16:34:59Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![sudara](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/9d8465/32.png) [@sudara](https://www.ruby-forum.com/u/sudara)\
**Post date:** [May 18, 2006, 4:34pm UTC](https://www.ruby-forum.com/t/model-madness-habtm-vs-through/60919/1 "2006-05-18T16:34:59Z")

</div>

This has me scratching my head:

a Person has many Things  
a Person has many Collections  
a Collection has many Things  
…Things in a Collection are ordered  
…Things in a Collection can be related to (created by) any User  
…a collection has additional attributes, such as a name etc

I am confused about habtm in rails (especially when using  
acts\_as\_habtm\_list) vs. going the :through route. Please tell me I am  
thinking too hard!

My current take:  
-_-_-_-_-_-_-_-_  
class Person \< ActiveRecord::Base  
has\_many :things  
has\_many :collections  
end

class Thing \< ActiveRecord::Base  
belongs\_to :person  
has\_and\_belongs\_to\_many :collections, :order =\> ‘position’  
end

class Collection \< ActiveRecord::Base  
belongs\_to :person  
has\_and\_belongs\_to\_many :thing\_collections, :order =\> ‘position’  
end

class ThingCollection \< ActiveRecord::Base  
has\_and\_belongs\_to\_many :collections  
has\_and\_belongs\_to\_many :things  
acts\_as\_list :scope =\> :collections  
end  
-_-_-_-_-_-_-_-_

Is that right?  
or is it better to do something like this:

-_-_-_-_-\*-  
class Person \< ActiveRecord::Base  
has\_many :things  
has\_many :collections  
end

class Thing \< ActiveRecord::Base  
belongs\_to :person  
belongs\_to :collection  
has\_many :collections, :through =\> :thing\_collections, :order =\>  
“position”  
end

class Collection \< ActiveRecord::Base  
belongs\_to :person  
has\_many :things, :through =\> :thing\_collections, :order =\>  
“position”  
end

class ThingCollection \< ActiveRecord::Base  
belongs\_to :collections  
belongs\_to :things  
acts\_as\_list :scope =\> :collection\_id  
end  
-_-_-_-_-_-_

Yes, I am in over my head.  
Yes, I am smart, and willing to learn.  
Yes, I want to built something that will last and be flexible…  
No, I haven’t even moved on past the model, because I wish to  
understand…

Thanks!  
sudara

---

<div class="post-metadata">

**Author:** ![sudara](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/9d8465/32.png) [@sudara](https://www.ruby-forum.com/u/sudara)\
**Post date:** [May 18, 2006, 5:10pm UTC](https://www.ruby-forum.com/t/model-madness-habtm-vs-through/60919/2 "2006-05-18T17:10:26Z")

</div>

Sudara,  
I think you’re thinking too hard. From what you described I don’t think  
you  
need such a complicated data model.

What is the purpose of ThingCollection? Isn’t Collection a collection of  
things?

Have you read this?

[http://blog.hasmanythrough.com/articles/2006/04/20/many-to-many-dance-off](http://blog.hasmanythrough.com/articles/2006/04/20/many-to-many-dance-off)

-Brian

---

<div class="post-metadata">

**Author:** ![sudara](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/9d8465/32.png) [@sudara](https://www.ruby-forum.com/u/sudara)\
**Post date:** [May 18, 2006, 5:23pm UTC](https://www.ruby-forum.com/t/model-madness-habtm-vs-through/60919/3 "2006-05-18T17:23:10Z")

</div>

The only reason for using habtm instead of :through is it’s  
simplicity. You don’t need to create a model class for the join table.  
If you use habtm, the table would be called collections\_things (the  
two tables in alphabetical order). Just using a simple habtm wouldn’t  
be enough for your purposes though, because you need it to be a list.  
Now, I don’'t know about acts\_as\_habtm\_list (by the name, it sounds  
like it might be quite useful for you), but I would do that using  
:through. Replace all your habtms with has\_many… :through =\>  
ThingCollection, and you’re set.  
Hope all that made sense.  
-Nathan

---

<div class="post-metadata">

**Author:** ![sudara](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/9d8465/32.png) [@sudara](https://www.ruby-forum.com/u/sudara)\
**Post date:** [May 20, 2006, 7:10pm UTC](https://www.ruby-forum.com/t/model-madness-habtm-vs-through/60919/4 "2006-05-20T19:10:32Z")

</div>

Thanks guys:

Brian:  
As far as I know, _some_ extra join model must exist if I want to employ  
lists. You are right, Collection is a collection of Things. But I would  
like to take advantage of the ordering built in with acts\_as\_list or  
acts\_as\_hatbm\_list, and so my impression is that I need a table with a  
position column and tell it to acts\_as\_list

That link is great - that is where I came from. Part of it was  
informative, part of it was over my head and confusing.

Nathan:  
Thanks for the confirmation…I believe what you suggested is working|

So, this is what I have:

-_-_-_-_-  
class Thing \< ActiveRecord::Base  
belongs\_to :person  
has\_many :collections, :through =\> :thing\_collection, :order =\>  
“position”  
end

class Collection \< ActiveRecord::Base  
belongs\_to :person  
has\_many :things, :through =\> :thing\_collection, :order =\>  
“position”  
end

class ThingCollection \< ActiveRecord::Base  
belongs\_to :collection  
belongs\_to :thing  
acts\_as\_list :scope =\> :collection, :order =\> :position  
end

-_-_-_-_-

As far as I understand it, I can use acts\_as\_list here, specifying that  
I want to access ThingCollection via Collections as the scope.

When I start to move into the controllers, I am not quite clear what the  
easiest way to access my variables are…but, then again I still have  
some basic things to learn.

For example, I am doing this ugly thing in my Collections controller, in  
order to make the items in the collection availble for sorting. I  
_know_ there is an easier way.

def order  
@items = ThingCollection.find(:all, :conditions =\> [  
“collection\_id=”, params[:id]])  
end

Thanks,  
sudara
