Question

I am getting a ActiveModel::MassAssignmentSecurity::Error: Can't mass-assign protected attributes: title when I have attr_accessible :title in the model. See the code and output of a console call below:

User model

# == Schema Information
#
# Table name: users
#
#  id              :integer          not null, primary key
#  name            :string(255)
#  email           :string(255)
#  created_at      :datetime         not null
#  updated_at      :datetime         not null
#  password_digest :string(255)
#  remember_token  :string(255)
#  admin           :boolean          default(FALSE)
#

class User < ActiveRecord::Base
  attr_accessible :name, :email, :password, :password_confirmation
  has_secure_password

  has_many :cycles, foreign_key: "manager_id"
  has_many :reverse_cycles, foreign_key: "employee_id", class_name: "Cycle"
  has_many :employees, through: :cycles
  has_many :managers, through: :reverse_cycles
  has_many :templates, foreign_key: "creator_id"

  before_save { self.email.downcase! }
  before_save :create_remember_token

  validates :name, presence: true, length: { maximum: 50 }
  VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
  validates :email, presence:   true,
                    format:     { with: VALID_EMAIL_REGEX },
                    uniqueness: { case_sensitive: false }
  validates :password, length: { minimum: 6 }
  validates :password_confirmation, presence: true

  #####  Functions  #####

  def create_cycle_as_employee!(other_user, date = 1.year.from_now)
    rcycle = reverse_cycles.create!(manager_id: other_user.id, ends_on: date)
    # self.reload
    rcycle
  end

  def create_cycle_as_manager!(other_user, date = 1.year.from_now)
    cycle = cycles.create!(employee_id: other_user.id, ends_on: date)
    # self.reload
    cycle
  end

  def create_template!(title)
    puts "made it here"
    templates.create!(title: title)
  end

  def is_employee_of?(other_user)
    cycles.find_by_manager_id(other_user.id)
  end

  def is_manager_of?(other_user)
    cycles.find_by_employee_id(other_user.id)
  end


  private

    def create_remember_token
      self.remember_token = SecureRandom.urlsafe_base64
    end
end

Template model

class Template < ActiveRecord::Base
  include PublicID

  attr_accessible :title #:creator_id, :deleted, :parent_id, :public_id, :title

  belongs_to :creator, class_name: "User"
  has_many :questions, class_name: "TemplateQuestion"

  validates :title, presence: true
  validates :creator_id, presence: true

  def create_question!(content, type = 0) 
    questions.create!(content: content, type: type)
  end

end

Stacktrace

1.9.3-p362 :004 > user.create_template!("test")
   (0.1ms)  begin transaction
   (0.1ms)  rollback transaction
ActiveModel::MassAssignmentSecurity::Error: Can't mass-assign protected attributes: title
  from /Users/r/.rvm/gems/ruby-1.9.3-p362@rails3tutorial2ndEd/gems/activemodel-3.2.    11/lib/active_model/mass_assignment_security/sanitizer.rb:48:in `process_removed_attributes'
  from /Users/r/.rvm/gems/ruby-1.9.3-p362@rails3tutorial2ndEd/gems/activemodel-3.2.    11/lib/active_model/mass_assignment_security/sanitizer.rb:20:in `debug_protected_attribute_removal'
  from /Users/r/.rvm/gems/ruby-1.9.3-p362@rails3tutorial2ndEd/gems/activemodel-3.2.    11/lib/active_model/mass_assignment_security/sanitizer.rb:12:in `sanitize'
  from /Users/r/.rvm/gems/ruby-1.9.3-p362@rails3tutorial2ndEd/gems/activemodel-3.2.11/lib/active_model/mass_assignment_security.    rb:230:in `sanitize_for_mass_assignment'
  from /Users/r/.rvm/gems/ruby-1.9.3-p362@rails3tutorial2ndEd/gems/activerecord-3.2.11/lib/active_record/attribute_assignment.    rb:75:in `assign_attributes'
  from /Users/r/.rvm/gems/ruby-1.9.3-p362@rails3tutorial2ndEd/gems/activerecord-3.2.11/lib/active_record/base.rb:497:in `initialize'
  from /Users/r/.rvm/gems/ruby-1.9.3-p362@rails3tutorial2ndEd/gems/activerecord-3.2.11/lib/active_record/reflection.rb:183:in `new'
  from /Users/r/.rvm/gems/ruby-1.9.3-p362@rails3tutorial2ndEd/gems/activerecord-3.2.11/lib/active_record/reflection.rb:183:in     `build_association'
  from /Users/r/.rvm/gems/ruby-1.9.3-p362@rails3tutorial2ndEd/gems/activerecord-3.2.11/lib/active_record/associations/association.    rb:233:in `build_record'
  from /Users/r/.rvm/gems/ruby-1.9.3-p362@rails3tutorial2ndEd/gems/activerecord-3.2.    11/lib/active_record/associations/collection_association.rb:434:in `block in create_record'
  from /Users/r/.rvm/gems/ruby-1.9.3-p362@rails3tutorial2ndEd/gems/activerecord-3.2.    11/lib/active_record/associations/collection_association.rb:149:in `block in transaction'
  from /Users/r/.rvm/gems/ruby-1.9.3-p362@rails3tutorial2ndEd/gems/activerecord-3.2.    11/lib/active_record/connection_adapters/abstract/database_statements.rb:192:in `transaction'
  from /Users/r/.rvm/gems/ruby-1.9.3-p362@rails3tutorial2ndEd/gems/activerecord-3.2.11/lib/active_record/transactions.rb:208:in     `transaction'
  from /Users/r/.rvm/gems/ruby-1.9.3-p362@rails3tutorial2ndEd/gems/activerecord-3.2.    11/lib/active_record/associations/collection_association.rb:148:in `transaction'
  from /Users/r/.rvm/gems/ruby-1.9.3-p362@rails3tutorial2ndEd/gems/activerecord-3.2.    11/lib/active_record/associations/collection_association.rb:433:in `create_record'
  from /Users/r/.rvm/gems/ruby-1.9.3-p362@rails3tutorial2ndEd/gems/activerecord-3.2.    11/lib/active_record/associations/collection_association.rb:123:in `create!'
  from /Users/r/.rvm/gems/ruby-1.9.3-p362@rails3tutorial2ndEd/gems/activerecord-3.2.    11/lib/active_record/associations/collection_proxy.rb:46:in `create!'
  from /Users/r/Sites/MicroEval/ror/app/models/user.rb:51:in `create_template!'
  from (irb):4
  from /Users/r/.rvm/gems/ruby-1.9.3-p362@rails3tutorial2ndEd/gems/railties-3.2.11/lib/rails/commands/console.rb:47:in `start'
  from /Users/r/.rvm/gems/ruby-1.9.3-p362@rails3tutorial2ndEd/gems/railties-3.2.11/lib/rails/commands/console.rb:8:in `start'
  from /Users/r/.rvm/gems/ruby-1.9.3-p362@rails3tutorial2ndEd/gems/railties-3.2.11/lib/rails/commands.rb:41:in `<top (required)>'
  from script/rails:6:in `require'
  from script/rails:6:in `<main>'1.9.3-p362 :005 > user.create_template!("test")

So big question is, why? Am I missing something? I checked for typos, but I'm assuming I'm either overlooking something or not understanding.

Was it helpful?

Solution

The issue here is that the attr_accessible ... statement is never reached. The reason is because of that erroneous include PublicID, and here's why:

Consider the following console statement:

Template.create(:title => "omg")

It will output the following stack trace:

1.9.3-p362 :001 > Template.create(:title => "omg")
TypeError: wrong argument type String (expected Module)
    from /Users/r/Sites/MicroEval/ror/app/models/template.rb:2:in `include'
    from /Users/r/Sites/MicroEval/ror/app/models/template.rb:2:in `<class:Template>'
    from /Users/r/Sites/MicroEval/ror/app/models/template.rb:1:in `<top (required)>'
    from /Users/r/.rvm/gems/ruby-1.9.3-p362@rails3tutorial2ndEd/gems/activesupport-3.2.11/lib/active_support/dependencies.    rb:469:in `load'
    from /Users/r/.rvm/gems/ruby-1.9.3-p362@rails3tutorial2ndEd/gems/activesupport-3.2.11/lib/active_support/dependencies.    rb:469:in `block in load_file'
    from /Users/r/.rvm/gems/ruby-1.9.3-p362@rails3tutorial2ndEd/gems/activesupport-3.2.11/lib/active_support/dependencies.    rb:639:in `new_constants_in'
    from /Users/r/.rvm/gems/ruby-1.9.3-p362@rails3tutorial2ndEd/gems/activesupport-3.2.11/lib/active_support/dependencies.    rb:468:in `load_file'
    from /Users/r/.rvm/gems/ruby-1.9.3-p362@rails3tutorial2ndEd/gems/activesupport-3.2.11/lib/active_support/dependencies.    rb:353:in `require_or_load'
    from /Users/r/.rvm/gems/ruby-1.9.3-p362@rails3tutorial2ndEd/gems/activesupport-3.2.11/lib/active_support/dependencies.    rb:502:in `load_missing_constant'
    from /Users/r/.rvm/gems/ruby-1.9.3-p362@rails3tutorial2ndEd/gems/activesupport-3.2.11/lib/active_support/dependencies.    rb:192:in `block in const_missing'
    from /Users/r/.rvm/gems/ruby-1.9.3-p362@rails3tutorial2ndEd/gems/activesupport-3.2.11/lib/active_support/dependencies.    rb:190:in `each'
    from /Users/r/.rvm/gems/ruby-1.9.3-p362@rails3tutorial2ndEd/gems/activesupport-3.2.11/lib/active_support/dependencies.    rb:190:in `const_missing'
    from (irb):1
    from /Users/r/.rvm/gems/ruby-1.9.3-p362@rails3tutorial2ndEd/gems/railties-3.2.11/lib/rails/commands/console.rb:47:in     `start'
    from /Users/r/.rvm/gems/ruby-1.9.3-p362@rails3tutorial2ndEd/gems/railties-3.2.11/lib/rails/commands/console.rb:8:in     `start'
    from /Users/r/.rvm/gems/ruby-1.9.3-p362@rails3tutorial2ndEd/gems/railties-3.2.11/lib/rails/commands.rb:41:in `<top (    required)>'
    from script/rails:6:in `require'    

As you can see there is an error with the include, and that is because the proper module has not been first required.

Adding a simple require "publicid" to the top of the Template model will ensure that the module can indeed be included.

As another note, the module lives in /lib where / refers to the root of your app.

Thanks to the @radar on #rubyonrails IRC channel for the answer.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top