user1585163
user1585163

Reputation: 21

Rails 3.1 can't mass assign protected attributes for non database model

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

Answers (1)

Chris Peters
Chris Peters

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

Related Questions