views:

1044

answers:

6

Running something like:

@users = User.find(:first, :select => "name, lastname, salary") for @user in @users do @user.salary = 100000 @user.save end

After this looking up in the Mysql table, the users aren't updated.

+15  A: 

ActiveRecord doesn't know the object's id, in order to save the data. So include the id field in :select, like the example below:

@users = User.find(:first, :select => "id, name, lastname, salary")

John Ruby
A: 

Try using .update or .update_attributes instead: those are designed for edits (as opposed to .save, which is for creating new rows)

Fuffbee
A: 

Using .save! will also throw an error if it fails to save.

James Deville
+2  A: 

John Ruby is correct that you need to include the id of the object in the select.
Also, you rarely need to use the :select option. You can with joins, or if there is a real performance issue with selecting the entire row, but this doesn't come up much.
And you really don't need to be setting all those variables to instance vars (@). @user in the loop can be a local var. If you do need all the users as @users you can do:

@users = User.find(:all, :select => "id, name, lastname, salary")
@users.each do |user|
  user.salary = 10000
  user.save
end

You might also want to look at ActiveRecord's update_all for simple changes. But note this doesn't call any save callbacks.

ScottD
A: 

May I help you?

A: 

I realize this is a pretty old question at this point, but the correct answer, I believe is that any objects returned by :select are read-only.

See the official Rails guide to Active Record querying, section 3.2:
http://guides.rubyonrails.org/active_record_querying.html

Curiously, I don't see this documented in the API.

WIlliam Jones