HABTM deprected: using has_many :through

Hi all,

I have a question about how utilizing has_many. I wrote the code without an editor & testing, so it could contain some errors.

Oh, and also don't mind the weird parent/child relationships here :slight_smile: http://pastie.caboo.se/139456

I want to be able to do something like: Parent.find(:first).children[0].active

How can I achieve this? With has_and_belongs_to_many this was easy. But I was fiddling with has_many and I could not get it working like this.

What am I doing wrong?

Thanks in advance!

Why do you say HABTM is deprecated? Just curious. I was always under the impression you use HABTM if you just want a simple relationship with no extra information and the :through option if you needed a more complex setup.

Nathan Esquenazi wrote:

Why do you say HABTM is deprecated? Just curious. I was always under the impression you use HABTM if you just want a simple relationship with no extra information and the :through option if you needed a more complex setup.

I read this in trac: DEPRECATED: Using additional attributes on has_and_belongs_to_many associations. Instead upgrade your association to be a real join model [DHH]

http://dev.rubyonrails.org/changeset/4123

If you read that again and highlight the key phrase:

DEPRECATED: USING ADDITIONAL ATTRIBUTES on has_and_belongs_to_many associations. Instead upgrade your association to be a real join model

As Nathan said, using habtm to represent a simple many-to-many relationship is not deprecated.

Rick Denatale wrote:

Hi all,

I have a question about how utilizing has_many. I wrote the code without an editor & testing, so it could contain some errors.

Oh, and also don't mind the weird parent/child relationships here :slight_smile: Parked at Loopia

I want to be able to do something like: Parent.find(:first).children[0].active

How can I achieve this? With has_and_belongs_to_many this was easy.
But I was fiddling with has_many and I could not get it working like this.

That looks plausible. what problems are you having (do you have a
ChildrenParent model ? You'll need one)

Fred

Right, he does and it need to belong_to both parent and child.

I also seems to me that it could use a better name, although I can't think of what that should be without a bit more knowledge of his domain.

class ChildrenParent   belongs_to :parent   belongs_to :child end

class Parent < ActiveRecord::Base   has_many :children_parents   has_many :children, :through => :children_parents end

class Child < ActiveRecord::Base   has_many :children_parents   has_many :parents, :through => :children_parents end

That should do it. :slight_smile:

--Jeremy

How about Birth? And if the :position attribute were birth order, it could be replaced by birthdate.

///ark

Tried the code above and got something like:

p = Parent.find(:first) p.children.length

=> 2

p.children_parents.length

=> 2

p.children_parents[0].position

=> 0

p.children[0].position

=> NoMethodError: undefined method `position' for #<Child:0xb76b4114>         from /usr/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/attribute_methods.rb:205:in `method_missing'         from (irb):3

And p.children[0].position is what I would like to use. When I use has_and_belongs_to_many this works.

I thought about using something like:

  alias_method(:method_missing_old, :method_missing)   def method_missing(methodname, *args)     return song.send(methodname) if args.empty?     child.send(methodname, args)   end

in the ChildrenParent class. But I don't know how fragile/stable this is.

Tried the code above and got something like:

Which code above in particular?

I used the code from Jeremy.

I used the code from Jeremy.

Okay, so the problem is this

p.children_parents[0].position

=> 0

p.children[0].position

=> NoMethodError: undefined method `position' for #<Child:0xb76b4114>

Which is right, Child has not position attribute it's in the ChildrenParent.

Now the problem is that a child has_many children_parents, so we can't just do

p.children[0].children_parent.position

We need to say WHICH of the many possible childrenParents we're talking about, Now I'm guessing that the logic actually dictates that there really is only one, in which case we can do

p.children[0].children_parent[0].position

or

p.children.find(:first).children_parent.find(:first).position

However the right way to do this, IMHO would be to do this:

class Child

    def position         children_parent.find(:first).position     end end

But of course this raises the question of why position isn't just a simple attribute of Child, in which case I'd seriously consider dropping back to HABTM.

If there really are multiple ChildrenParents associated with a single Child, then you do need to figure out which one you are getting the position of.

Thanks Rick.

I'll explain what I'm trying to do.

I'm creating a website where people (at our company) can vote at songs. The song with the most votes gets played.

So I now have: Playlist, Song, PlaylistItem

But I dont't find:

p = Playlist.find(:first) p.playlist_items[0].position p.playlist_items[0].top_top p.songs[o].title p.songs[o].artist

make sence.

Maybe it's the naming of the objects I've done. Does someone know a better name for the join class so it makes more sence doing the position-thing on that model instead of song?

So where are the votes in this model?

Why not put a vote count attribute in the Song which voting increments?

If you want to actually hold the votes in the database then you can do something like:

class Vote < ActiveRecord::Base   belongs_to :song   belongs_to :voter   .. end

def Song < ActiveRecord::Base   has_many :votes, :counter_cache => true # and add a votes_count column to the table

  def self.most_popular       find(:first, :order => "vote_count DESC")   end ... end

I'm struggling, possibly, with the *exact* same problem. Hmm, except that I'm using has_many :through, while yours is HABTM :frowning:

That being said, how is your interface? Do you have an interface to associate a specific "child" with a "parent"?

Feel free to contact me by e-mail to trade notes.

-Thufir

What about foster children, or step-parents?

-Thufir