HABTM loses 'additional fields' when using :include in find


#1

Hi folks-

I’ve come across a snag that may be a bug, but I’m not sure…

When I do the following (example)–
@members = @project.members.find(:all)

I get my @members array and it also has additional fields from the table
“parts_members”. Great.

However, when I do:
@members = @project.members.find(:all,
:include => [ :state ])

where ‘state’ is a field in the ‘members’ table, for some reason those
additional fields get clobbered. Am I doing something wrong?

Jake


#2

I don’t normally like to bump my own messages, but I’m still having this
problem. Has anyone else discovered it?

Jake

Jake J. wrote:

Hi folks-

I’ve come across a snag that may be a bug, but I’m not sure…

When I do the following (example)–
@members = @project.members.find(:all)

I get my @members array and it also has additional fields from the table
“parts_members”. Great.

However, when I do:
@members = @project.members.find(:all,
:include => [ :state ])

where ‘state’ is a field in the ‘members’ table, for some reason those
additional fields get clobbered. Am I doing something wrong?

Jake


#3

I think it’s a little unclear what you’re trying to do. find(:include
=> …) specifies table joins. For that to work, you would have to
have an association already defined… example would be:

class Member < ActiveRecord::Base
belongs_to :state
end

class State < ActiveRecord::Base
has_many :members
end

If that is the case, by default you would have a state_id' field in Member (not astate’ field) as a FK to the states table.
Then, :include => [ :state ] should include that association.

If you’re doing what it looks like you’re trying to do (assign an
enumerated value, State, to each member), you might want to look at
the ActiveRecord Enumerations plugin (http://wiki.rubyonrails.com/
rails/pages/Plugins).

Brad E.
866-EDIGERS


#4

I haven’t really used HABTM much precisely for this reason…
whenever the join-table information grows larger than just left_id
and right_id, I’ve usually refactored it into a separate model. There
is a sidebar from DHH in AWDWR about this, and it seems most people
generally use separate models for this situation. (I actually can’t
recall any situation in my Rails experience where a HABTM
relationship has survived into production code without being replaced
by a separate model.)

As to why the eager loading clobbers the additional fields, I’m not
sure. I would suggest taking a look at the SQL queries being
generated for the find()… maybe it’s joining the tables differently
than you would expect.

Good luck–
be

On Nov 25, 2005, at 5:38 PM, Jake J. removed_email_address@domain.invalid


#5

Hi Brad-

Sorry if this was confusing – I’m still trying to figure out the best
way to explain some of these database setups.

I have an association between tables ‘projects’ and ‘members’. This
association is in a table called ‘projects_members’. The DB would look
like: (this is a simplified, made up database)

projects

id
name

members

id
name
state_id --> Points to another table called ‘states’

projects_members

project_id
member_id
some_other_column

According to the documentation, when the HABTM relationship is setup
between ‘projects’ and ‘members’, the ‘some_other_column’ is supposed to
magically appear as an attribute that I can read out. The HABTM doc
calls these “additional fields added to the join table”.

This works just fine except when I use the ‘:include’ option to
eager-load ‘states’. When I use :include, the “additional fields” get
clobbered.

A workaround is to define a model for the join table, but this seems to
be something that should work anyhow. I’m also curious – how often do
folks use HABTM rather than just define a model for the join table.
Seems there’s always something in the join that makes it just a little
outside the realm of HABTM.

Jake

brad wrote:

I think it’s a little unclear what you’re trying to do. find(:include
=> …) specifies table joins. For that to work, you would have to
have an association already defined… example would be:

class Member < ActiveRecord::Base
belongs_to :state
end

class State < ActiveRecord::Base
has_many :members
end

If that is the case, by default you would have a state_id' field in Member (not astate’ field) as a FK to the states table.
Then, :include => [ :state ] should include that association.

If you’re doing what it looks like you’re trying to do (assign an
enumerated value, State, to each member), you might want to look at
the ActiveRecord Enumerations plugin (http://wiki.rubyonrails.com/
rails/pages/Plugins).

Brad E.
866-EDIGERS