# Help updating cross-reference table

**URL:** <https://www.ruby-forum.com/t/help-updating-cross-reference-table/125199>\
**Category:** Rails\
**Created:** [January 6, 2008, 11:36pm UTC](https://www.ruby-forum.com/t/help-updating-cross-reference-table/125199 "2008-01-06T23:36:13Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![weloki](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/w/a587f6/32.png) [@weloki](https://www.ruby-forum.com/u/weloki)\
**Post date:** [January 6, 2008, 11:36pm UTC](https://www.ruby-forum.com/t/help-updating-cross-reference-table/125199/1 "2008-01-06T23:36:13Z")

</div>

I am trying to update a cross-reference table in a database when the  
user submits a simple form. The table has three columns, ‘id’,  
‘location\_id’ and ‘user\_id’.

Using this action, I get no errors, but nothing happens to the table:

```
def update
  @user = User.find(params[:id])
  @locations = Location.find(:all)
  @locationsusers = LocationsUser.find(params[:id])
  if @locationsusers.update_attributes(:user_id => @user,

```

:location\_id =\> @locations)  
flash[:notice] = ‘Data was successfully updated.’  
redirect\_to :action =\> ‘list’  
else  
render :action =\> ‘edit’  
end  
end

If I try to substitute the update\_attributes line with:

if @locationsusers.update\_attributes(params[:id])

I see the error,  
“undefined method `stringify\_keys!’ for “3”:String”.

If I try to do this:

@locationsusers = LocationsUser.find(:all)  
if @locationsusers.update\_attributes(params[:id])

I see the error,  
“NoMethodError in UserController#updateLocation  
undefined method `update\_attributes’”

How can I do this correctly?

---

<div class="post-metadata">

**Author:** ![weloki](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/w/a587f6/32.png) [@weloki](https://www.ruby-forum.com/u/weloki)\
**Post date:** [January 7, 2008, 3:30pm UTC](https://www.ruby-forum.com/t/help-updating-cross-reference-table/125199/2 "2008-01-07T15:30:38Z")

</div>

Quoting Jeffrey L. Taylor [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> > ```
> > @user = User.find(params[:id])
> > 
> > ```
> 
> if @locationusers.update\_attributes(:user\_id =\> @user.id,  
> :location\_id =\> @locations.map(&:id)
> 
> But what you probably want is a :has\_many :through association table. Off the  
> top of my head:

[snip]  
If there will never be any values in the cross-reference (AKA join)  
table,  
i.e., just the three columns mentioned, the conceptually simpler  
has\_and\_belongs\_to\_many relationship works. IIRC, the join table should  
be  
named LocationsUsers. There is a way to override the join table name,  
perhaps  
through:

Class User \< ActiveRecord::Base  
has\_and\_belongs\_to\_many :locations, :through =\> :location\_users  
end

Class Location \< ActiveRecord::Base  
has\_many :location\_users  
has\_many :users, :through =\> :location\_users  
end

The update code is the same. Oh, and the class names in the previous  
example  
should be singular.

HTH,  
Jeffrey

---

<div class="post-metadata">

**Author:** ![weloki](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/w/a587f6/32.png) [@weloki](https://www.ruby-forum.com/u/weloki)\
**Post date:** [January 7, 2008, 11:02am UTC](https://www.ruby-forum.com/t/help-updating-cross-reference-table/125199/3 "2008-01-07T11:02:06Z")

</div>

Quoting Mr. Bill [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> ```
> @locationsusers = LocationsUser.find(params[:id])
> if @locationsusers.update_attributes(:user_id => @user,
> 
> ```
> 
> :location\_id =\> @locations)

Try:  
if @locationusers.update\_attributes(:user\_id =\> @user.id,

However, since @locations is an array of Location(s), this code probably  
isn’t  
what you want at all. You could do:

if @locationusers.update\_attributes(:user\_id =\> @user.id,  
:location\_id =\> @locations.map(&:id)

But what you probably want is a :has\_many :through association table.  
Off the  
top of my head:

Class LocationUsers \< ActiveRecord::Base  
belongs\_to :user  
belongs\_to :location  
end

Class Users \< ActiveRecord::Base  
has\_many :location\_users  
has\_many :locations, :through =\> :location\_users  
end

Class Locations \< ActiveRecord::Base  
has\_many :location\_users  
has\_many :users, :through =\> :location\_users  
end

def update  
@user = User.find(params[:id])  
@locations = Location.find(:all)  
@locations.each {|l| @user.locations \<\< l}  
end

HTH,  
Jeffrey

---

<div class="post-metadata">

**Author:** ![weloki](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/w/a587f6/32.png) [@weloki](https://www.ruby-forum.com/u/weloki)\
**Post date:** [January 7, 2008, 4:45pm UTC](https://www.ruby-forum.com/t/help-updating-cross-reference-table/125199/4 "2008-01-07T16:45:04Z")

</div>

Thank you for your assistance Jeffrey. Your comments have helped.

When I try to do:  
def update  
@user = User.find(params[:id])  
@locations = Location.find(:all)  
@locations.each {|l| @user.locations \<\< l}  
end

I see this error:  
“TypeError in UserController#updateLocation  
can’t convert Location into Integer”

When I do:  
@locationsusers = LocationsUser.find(params[:id])  
if @locationsusers.update\_attributes(:user\_id =\> @user.id, :location\_id  
=\> @locations.map(&:id))

I don’t see any errors, but nothing changes in the database table.  
Is there something else I’m missing?

Jeffrey L. Taylor wrote:

> Quoting Jeffrey L. Taylor [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):
> 
> > > ```
> > > @user = User.find(params[:id])
> > > 
> > > ```
> > 
> > if @locationusers.update\_attributes(:user\_id =\> @user.id,  
> > :location\_id =\> @locations.map(&:id)
> > 
> > But what you probably want is a :has\_many :through association table. Off the  
> > top of my head:
> 
> [snip]  
> If there will never be any values in the cross-reference (AKA join)  
> table,  
> i.e., just the three columns mentioned, the conceptually simpler  
> has\_and\_belongs\_to\_many relationship works. IIRC, the join table should  
> be  
> named LocationsUsers. There is a way to override the join table name,  
> perhaps  
> through:
> 
> Class User \< ActiveRecord::Base  
> has\_and\_belongs\_to\_many :locations, :through =\> :location\_users  
> end
> 
> Class Location \< ActiveRecord::Base  
> has\_many :location\_users  
> has\_many :users, :through =\> :location\_users  
> end
> 
> The update code is the same. Oh, and the class names in the previous  
> example  
> should be singular.
> 
> HTH,  
> Jeffrey

---

<div class="post-metadata">

**Author:** ![weloki](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/w/a587f6/32.png) [@weloki](https://www.ruby-forum.com/u/weloki)\
**Post date:** [January 7, 2008, 7:23pm UTC](https://www.ruby-forum.com/t/help-updating-cross-reference-table/125199/5 "2008-01-07T19:23:19Z")

</div>

Eureka! The action below did the trick.  
Thank you for all your help Jeffrey. The suggestions on the models  
worked also.

def update  
@user = User.find(params[:id])  
@locations = Location.find(:all)  
@locations.each do |location|  
@locationsids = location.id  
end  
@locationsusers = LocationsUser.new  
@locationsusers.user\_id = @user.id  
@locationsusers.location\_id = @locationsids.id  
if @locationsusers.update\_attributes(params[:locations\_users])  
flash[:notice] = ‘User was successfully updated.’  
redirect\_to :action =\> ‘list’  
else  
render :action =\> ‘edit’  
end  
end
