help updating cross-reference table

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?

Quoting Mr. Bill <rails-mailing-list@andreas-s.net>:

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)

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

Quoting Jeffrey L. Taylor <ror@austinblues.dyndns.org>:

Quoting Mr. Bill <rails-mailing-list@andreas-s.net>:
>
> 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)

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:

[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

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:

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