Reputation: 21
The part of rails 3.1 that handles attr_accessor
is apparently broken.
I have several models that do not have a database at all and some that have attributes that are not persisted.
Example:
class User < ActiveRecord::Base
#persisted attribs
attr_accessible :name, :email, :password, :password_confirmation, :is_admin, :permissions
#non persisted attribs<br />
attr_accessor :roseburg, :kfc, :kcpl
........
if I attempt to save the the user in the controllers create or update with
def create<br />
@user = User.new(params[:user])
or
def update
@user = User.find(params[:id])
respond_to do |format|
if @user.update_attributes(params[:user])
I get a error something like Cannot mass assign protected attributes :roseburg, :kfc,
:kcpl
The workaround is to populate the attributes and use the save method.
def create
@user = User.new
(params[:user]).each do |attr_name, attr_value|
if @user.respond_to?("#{attr_name}")
@user.send("#{attr_name}=", attr_value)
end
end
@user.save
.....
and
def update
@user = User.find(params[:id])
respond_to do |format|
(params[:user]).each do |attr_name, attr_value|
if @user.respond_to?("#{attr_name}")
@user.send("#{attr_name}=", attr_value)
end
end
if @user.save
....
my question is what effect does this have on security?
Upvotes: 1
Views: 1052
Reputation: 18090
When you pass a hash to a method like new
, create
, or update_attributes
, Rails will make sure that you can only mass-assign attributes that are allowed with attr_accessible
(or, alternatively, will not allow attributes blacklisted with attr_protected
).
If you don't add :roseburg
, :kfc
, and :kcpl
to attr_accessible
, it will throw a mass-assignment error like the one that you describe.
Having them defined by attr_accessor
only guarantees that you'll have setters and getters (e.g., roseburg=
and roseburg
), which has nothing to do with Rails's mass-assignment checks. attr_accessor
is actually a Ruby construct, not anything provided by ActiveRecord.
If you don't add the non-persisted attributes to attr_accessible
, you'll need to manually assign the values when initializing your model instance like you describe in your question.
Upvotes: 1