RoR: How to modify the controller to accept update several params only?
Here is the code generated by rails:
def update
@user = User.find(params[:id])
respond_to do |format|
if @user.update_attributes(params[:user])
flash[:notice] = 'User was successful开发者_JAVA百科ly updated.'
format.html { redirect_to(@user) }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => @user.errors, :status => :unprocessable_entity }
end
end
end
But I don't want user to update the whole user, assume that my user have fname, lname and gender, instead of remove the gender from the view, I want to restrict that the update method ONLY accept fname and lname only, if he/she want to update the gender, I won't allow him/her to do so. How can I restrict the user to do so? thank you.
or add a custom @user.update_only()
method, which makes it also easier to reuse in different contexts...
class User
def update_only(attrs = {}, *limit_to)
update_attributes(attrs.delete_if { |k,v| !limit_to.include?(k.to_sym) })
end
end
Then just do something along the lines of
@user.update_only(params[:user], :fname, :lname)
There are two methods in ActiveRecord that come in handy in cases like these, attr_protected
and attr_accessible
.
You use them like this:
class MyModel < ActiveRecord::Base
attr_accessible :fname, :lname #Allow mass-assignment
attr_protected :secret #Do not allow mass-assignment
end
model = MyModel.new(:fname => "Firstname", :lname => "Lastname", :secret => "haha")
puts model.fname # "Firstname"
puts model.lname # "Lastname"
puts model.secret = nil # Can not be set through mass-assignment
model.secret = "mysecret" # May only be assigned like this
puts model.secret # "mysecret"
However, if you only need this functionality at one place, then Salil's solution will work just as well.
One thing to note is that you should use attr_acessible to whitelist attributes that are OK to mass-assign, and make every other attribute protected. By doing so, you hinder mean people for updating data they are not supposed to touch.
See the docs for more info.
Use Hash parameters of the update_attributes
@user = User.find(params[:id])
@user.update_attributes(:fname=>params[:user][:fname], :lname=>params[:user][:lname])
You can delete unwanted attributes from the param[:user]
Hash:
# ...
attributes = params[:user]
gender = attributes.delete :gender
raise SomeError unless gender.blank?
if @user.update_attributes(attributes)
# ...
end
# ...
This code removes :gender
from the Hash and checks if it is filled in. If so, an exception is raised. Of course you could give a nice warning or silently ignore the fact that the gender was filled in.
精彩评论