HABTM and getting to arrays from either direction

I didn’t find exactly an answer on this one, so I’d like to get a
clarification from folks who live & breathe HABTM.

class foo
has_and_belongs_to_many :bars
end

class bar
has_and_belongs_to_many :foos
end

(and yes, I have a bars_foos table in my db)

def test_habtm
bar = Bar.new
foo = Foo.new

foo.bars<<bar
assert !foo.bars.empty?
assert !bar.foos.empty?
end

My first assert passes just fine. But the 2nd fails. Am I wrong on the
concepts of HABTM? Shouldn’t the << operator add to the join table and
therefore the next find from either object return a non-empty array?

thx,
–dwf

DWFrank wrote:

I didn’t find exactly an answer on this one, so I’d like to get a
clarification from folks who live & breathe HABTM.

class foo
has_and_belongs_to_many :bars
end

class bar
has_and_belongs_to_many :foos
end

(and yes, I have a bars_foos table in my db)

def test_habtm
bar = Bar.new
foo = Foo.new

foo.bars<<bar
assert !foo.bars.empty?
assert !bar.foos.empty?
end

My first assert passes just fine. But the 2nd fails. Am I wrong on the
concepts of HABTM? Shouldn’t the << operator add to the join table and
therefore the next find from either object return a non-empty array?

<< acts different depending on whether the record has been saved or not.
If it is not a new record (has already been saved), the join table will
be updated when << is sent. If it hasn’t yet been saved, it has no id to
put in the join table, so it just saves the associated object in the
bars collection and waits to create the entry in the join table when it
gets saved. Try saving the objects and see what happens then.


Josh S.
http://blog.hasmanythrough.com/

Figured out my problem. Validation was preventing the save of a foo
within the test code.

I did the smart thing and made EXACTLY the code above and it
bar.foos.empty? is true.

What I did find odd was that bar.foos.include?(foo) doesn’t work. I’m
sure this has something to do with ActiveRecord arrays. But I’m now
using bar.foos.find(foo.id) and I’m happy.

thx,
–dwf

DWFrank wrote:

My first assert passes just fine. But the 2nd fails. Am I wrong on the
concepts of HABTM? Shouldn’t the << operator add to the join table and
therefore the next find from either object return a non-empty array?

Not an HABTM expert but…

The foos.bars collection is not empty because it’s an in-memory array
to which you’ve explicitly appended bar. The bar.foos collection
won’t include foo until foo is saved (also saving bar and creating
the join table entry).

I suppose Rails could be written to automatically keep the reverse
collection in sync, both prior to and through saves, but the code
would be a bit tricky.


We develop, watch us RoR, in numbers too big to ignore.