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 E. 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

On 1/16/08, Leon B. [email protected] wrote:

[DHH]
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

My blog on Ruby
http://talklikeaduck.denhaven2.com/

Rick Denatale wrote:

On 1/16/08, Leon B. [email protected] wrote:

[DHH]
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

My blog on Ruby
http://talklikeaduck.denhaven2.com/

Yes, but I have some additional attributes I want to include in the
join. One of this is :position.

But let’s not argue over if it’s deprecated or not. Is there a rails way
to achieve what I want?

On 16 Jan 2008, at 08:37, Leon B. wrote:

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

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

On Jan 16, 2008 3:37 AM, Leon B. [email protected]
wrote:

I want to be able to do something like:


http://www.jeremymcanally.com/

My books:
Ruby in Practice

My free Ruby e-book

My blogs:

http://www.rubyinpractice.com/

On Jan 16, 8:42 am, “Jeremy McAnally” [email protected]
wrote:

class ChildrenParent
belongs_to :parent
belongs_to :child
end

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

///ark

On 1/16/08, Frederick C. [email protected] wrote:

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

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.


Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

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:inmethod_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.

I used the code from Jeremy.

On 1/16/08, Leon B. [email protected] wrote:

Tried the code above and got something like:

Which code above in particular?

/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.

Posted via http://www.ruby-forum.com/.


Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

On 1/16/08, Leon B. [email protected] wrote:

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.


Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

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?

On 1/17/08, Leon B. [email protected] wrote:

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


Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

On Wed, 16 Jan 2008 09:37:18 +0100, Leon B. wrote:

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

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

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

On Wed, 16 Jan 2008 18:55:01 -0500, Rick DeNatale wrote:

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.

What about foster children, or step-parents?

-Thufir