How to update a Protected Attributes

Hello All,

I am trying to update a protected attribute called 'picture'. I am forced (I think) to use the following technique.

#first find a record or object @user = User.find(:some_id_here) .. .. # then assign the new value to protected attribute like this @user.picture ="somenewpicture.jpg"

#and then update the object like this... @user.update_attributes(other_updated_attributes_hash)

But instead I would like the following technique to update the object and save to db.

@user = User.update(15, {:user_name => 'Samuel', :group => 'expert', :picture="somenewpicture.jpg"})

The above technique does not update the picture attribute in db because its protected attribute.

Is it possible to update the protected attributes using Class.update method??

Is it not inefficient to find first unnecessarily, the object (record) as in the first technique and then save back to db. This can be slower in case of large database, where we have to unnecessarily find a record even though we know the record which we want to update, and thus making unnecessary query to find a record.

Is there any efficient method to do this along with updating protected attributes?

Both techniques are analogous in that sense, they first find(id) and then call update_attributes on the model object. Protected attributes are protected in any kind of mass-assignment, that's the point of being protected.

To bypass that safety and be able to work without a model object use update_all or grab the connection.

-- fxn

Thanks for this hint. But its quite a strange thing, that rails allows to set the protected attributes manually and then use the usual save method to create a new record/object, but the same thing isn't allowed while updating..I would have liked a flavor of Class.update() method where it allows me to set the protected attributes (probably passing a separate hash as to method call).

Anyways thanks for your answer!

What do you mean here?

-- fxn

I mean that say for example if I am creating a new record, I can do the following.

# here is the mass-assignment for the non protected attributes. @user= User.new(params[:user]) .. .. #now the manual assignment of protected attributes. @user.picture = "my_avatar.jpg"

#then I save the object and store in db if @user.save ... else .. end

You see its quite simple above to mass-assign the non protected attributes and then manually the set the protected attributes and finally save it to db.

However, in case of update, there is no similar technique like above that will allow me to mass-assign the non-protected attributes and then pickup the protected attributes and assign them manually, and finally save to db.

If I use the update_all method i need to provide all the list of attributes that i need to update and a condition. This is cumbersome in case i have a lot of non-protected attributes against only one or two protected attributes. Even if i have to update say only one protected attribute, I have to manually assign all the other attributes(may be 10 or 12) that i wish to update, that could have been done through mass-assignment.

if i don't use a update_all method, I need to find the object first.

@user = User.find(id)

set its protected attributes

@user.picture="new_image.jpg"

and then update to db

@user.update_attributes(params[:user]) # done by mass-assignment.

But here, i need to find the record first....

Instead i would have wished that, i need not find the object first, but still have the convenience as above.

Instead I would have wished a method say User.update(record_id, params_attributes_hash, protected_attributes_hash)

here, "params_attributes_hash" is for mass-assignment. So I don't need to care about, will be done automatically. "protected_attributes_hash" would be the protected attributes that i want to update.

Isn't this would be more convenient and efficient?

Let me know your thoughts, or if anything similar exists.

Penuel

The order is reversed, but for existing records you do something similar:

    @user = User.find(params[:id])     @user.score += 50 # manual assignment to protected attribute     if @user.update_attributes(params[:user]) # ignores protected keys       ...     else       ...     end

-- fxn

I have written a blog post on this subject: http://lassebunk.dk/2010/07/09/mass-assigning-protected-attributes-in-rails/

Hope this helps.

Best regards, Lasse