HABTM relations


#1

Hi,

I have 3 tables with HABTM relation.

USERS -> QUOTE_TO_USER <- QUOTES

Table QUOTE_TO_USER has 3 attributes: quote_id, user_id, component.

I have a form where I can tie multiple users to QUOTE. This is easy one,
thru “user_ids” (@quote[:user_ids] = @params[:quote][:user_ids]).

In this form I have all users and I just check those I want to tie to
this quote, however there’s one more attribute COMPONENT (the value of
the COMPONENT atribute is chosen from drop-down in this form), but I
don’t know how to save this change in QUOTE_TO_USER table. Need to make
multiple save for those users that I checked (tied with QUOTE table).

I hope I made my problem clear to you,

thanks for all ideas…and your help…

milos kelemen


#2

Hi Milos ~

At first glance it looks like you need to name your join table
users_quotes. Component should not be in your join table, but in one of
your tables involved in the join. Is there are reason to have component
in
that table? I am unclear on what you are trying to accomplish.

Ben


#3

my model looks just fine:

has_and_belongs_to_many :users,
:join_table => ‘quote_to_user’,
:foreign_key => ‘quote_id’,
:association_foreign_key => ‘user_id’

I’ll try to describe it:

I need to tie USER to QUOTE, this works just fine. In my form I check
those users I want to tie with QUOTE. There’s no problem to save this.
So it means that the model is good.

I gotta have this attribute in join table, bacause user can be tied to
one or more quotes and the value of component can be also different.
So lets say that user JOHN(id = 100) is tied to QUOTE(id = 200) and the
value of component is (molding). Another user in the same form will be
Mike(id = 101) and value of component is (tooling). Then the join table
should have these records:

user_id quote_id component
100 200 molding
101 200 tooling

Both users can be also tied with another QUOTE(id = 201) with different
value of component.

I hope this helps…

well…?

thanks for your answer…

milos


#4

Milos,

A couple of observations/comments for you.

First, are you dealing with a legacy database schema here which is
forcing you to use the join table “quote_to_user”? The reason I ask is
becuase if this is a new application that you are building, I strongly
recommend taking the “preferred” Rails way of doing HABTM
relationships by calling your table “quotes_users”. This will simplify
your relationship method quite a bit and give your application a more
“rails like” look and feel.

Second, I think the method you are looking for is called
“push_with_attributes”. This method allows one to save additional
attributes in the join table (look at
http://api.rubyonrails.com/classes/ActiveRecord/Associations/ClassMethods.html#M000474
for further help). So your assign method will look something like
this:

@quote.users.push_with_attributes(Quote.create(@params[:quote]),
{“component” => @params[:quote][:component]})

Hope that helps.


DeLynn B.
removed_email_address@domain.invalid


#5

but attribute ‘COMPONENT’ is not a part of QUOTE model
(@params[:quote][:component]) and I dont know how to prepare/change my
form to get this data (component attribute to each user)…

Sorry, I was going off of your previous code post which had
@quote[:user_ids] = @params[:quote][:user_ids]”. It will probably
need to be this then:

@quote.users.push_with_attributes(User.create(@params[:user]),{“component”

=> @params[:user][:component]})


DeLynn B.
removed_email_address@domain.invalid


#6

Thanks,

I was playing around with this push_with_attributes() method, however no
progress.

This is how assign method should look like:
@quote.users.push_with_attributes(Quote.create(@params[:quote]),{“component”
=> @params[:quote][:component]})

but attribute ‘COMPONENT’ is not a part of QUOTE model
(@params[:quote][:component]) and I dont know how to prepare/change my
form to get this data (component attribute to each user)…

hm…

–milos


#7

Kevin O. wrote:

I have a form where I can tie multiple users to QUOTE. This is easy one,
thanks for all ideas…and your help…

Basically you create a new model to handle the components part and
anything else you want to stuff in there.

Take a look at this…
http://www.ruby-forum.com/topic/24128#7157

_Kevin

thanks kevin, i’ll try it…


#8

milos kelemen wrote:

Hi,

I have 3 tables with HABTM relation.

USERS -> QUOTE_TO_USER <- QUOTES

Table QUOTE_TO_USER has 3 attributes: quote_id, user_id, component.

I have a form where I can tie multiple users to QUOTE. This is easy one,
thru “user_ids” (@quote[:user_ids] = @params[:quote][:user_ids]).

In this form I have all users and I just check those I want to tie to
this quote, however there’s one more attribute COMPONENT (the value of
the COMPONENT atribute is chosen from drop-down in this form), but I
don’t know how to save this change in QUOTE_TO_USER table. Need to make
multiple save for those users that I checked (tied with QUOTE table).

I hope I made my problem clear to you,

thanks for all ideas…and your help…

milos kelemen

Another alternative relationship structure may actually be useful here.

user has_many components
quotes has_many components
components belongs_to user
components belongs_to quotes

Basically you create a new model to handle the components part and
anything else you want to stuff in there.

Take a look at this…
http://www.ruby-forum.com/topic/24128#7157

_Kevin


#9

DeLynn B. wrote:

=> @params[:user][:component]})


DeLynn B.
removed_email_address@domain.invalid

yes I found that, however it throws an error:
undefined method `component=’ for #User:0x58a24d0

my views looks like this:

<%= text_field “user”, “component”, :size => “30” %>

this I found as a problem…what’s wrong…?


#10

DeLynn B. wrote:

=> @params[:user][:component]})


DeLynn B.
removed_email_address@domain.invalid

Hi DeLynn,

can you please tell me how to collect these data from the form. how
should the view code look like…?

I tried <%= text_field “user”, “component” %> but it throws an error
saying the component is not part of user model…which is true :slight_smile:

any help…?

thanks a lot,

milos kelemen

thanks,


#11

I tried <%= text_field “user”, “component” %> but it throws an error
saying the component is not part of user model…which is true :slight_smile:

I think you are going to have to use a text_field_tag instead of
text_field. You’ll be able to specify your own name this way, and then
you can access it separately in your controller.

The other option for you might also be the new has_many :through
support that is in Edge Rails. I haven’t played with it yet, but after
reading the message that Kevin linked to earlier, it sort of sounds
like that might be a better answer.


DeLynn B.
removed_email_address@domain.invalid


#12

milos kelemen wrote:

Table QUOTE_TO_USER has 3 attributes: quote_id, user_id, component.
I hope I made my problem clear to you,
quotes has_many components

thanks kevin, i’ll try it…

Hi kevin,

i was trying this, however I’m having difficulties. The new model would
be components, right? How would the view page look like…?
@components[‘component’] …?

thanks again,

klmn