Model Madness: habtm vs through


#1

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


#2

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

-Brian


#3

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


#4

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