How is attr_accessible used in Rails 4?

Ruby on-RailsRuby on-Rails-4

Ruby on-Rails Problem Overview


attr_accessible seems to no longer work within my model.

What is the way to allow mass assignment in Rails 4?

Ruby on-Rails Solutions


Solution 1 - Ruby on-Rails

Rails 4 now uses strong parameters.

Protecting attributes is now done in the controller. This is an example:

class PeopleController < ApplicationController
  def create
    Person.create(person_params)
  end

  private

  def person_params
    params.require(:person).permit(:name, :age)
  end
end

No need to set attr_accessible in the model anymore.

Dealing with accepts_nested_attributes_for

In order to use accepts_nested_attribute_for with strong parameters, you will need to specify which nested attributes should be whitelisted.

class Person
  has_many :pets
  accepts_nested_attributes_for :pets
end

class PeopleController < ApplicationController
  def create
    Person.create(person_params)
  end

  # ...

  private

  def person_params
    params.require(:person).permit(:name, :age, pets_attributes: [:name, :category])
  end
end

Keywords are self-explanatory, but just in case, you can find more information about strong parameters in the Rails Action Controller guide.

Note: If you still want to use attr_accessible, you need to add protected_attributes to your Gemfile. Otherwise, you will be faced with a RuntimeError.

Solution 2 - Ruby on-Rails

If you prefer attr_accessible, you could use it in Rails 4 too. You should install it like gem:

gem 'protected_attributes'

after that you could use attr_accessible in you models like in Rails 3

Also, and i think that is the best way- using form objects for dealing with mass assignment, and saving nested objects, and you can also use protected_attributes gem that way

class NestedForm
   include  ActiveModel::MassAssignmentSecurity
   attr_accessible :name,
                   :telephone, as: :create_params
   def create_objects(params)
      SomeModel.new(sanitized_params(params, :create_params))
   end
end

Solution 3 - Ruby on-Rails

An update for Rails 5:

gem 'protected_attributes' 

doesn't seem to work anymore. But give:

gem 'protected_attributes_continued'

a try.

Solution 4 - Ruby on-Rails

We can use

params.require(:person).permit(:name, :age)

where person is Model, you can pass this code on a method person_params & use in place of params[:person] in create method or else method

Solution 5 - Ruby on-Rails

  1. Update Devise so that it can handle Rails 4.0 by adding this line to your application's Gemfile:

    gem 'devise', '3.0.0.rc'

Then execute:

$ bundle

2) Add the old functionality of attr_accessible again to rails 4.0

Try to use attr_accessible and don't comment this out.

Add this line to your application's Gemfile:

gem 'protected_attributes'

Then execute:

$ bundle

Solution 6 - Ruby on-Rails

I had to migrate a Rails app from 3.2 to 6.1 so even gem 'protected_attributes' was not an option. I appreciate the arguments for using require().permit() in the controller, but I didn't want to retype or cut and paste all those attributes from the models, so I decided instead to use this initializer code (put in a file in config/initializers):

# fix attr_accessible in an initializer
# wrap ActionController::Parameters code in singleton method defined
# from attr_accessible so controller code can call class method
# to get permitted parameter list
# e.g. model: class A < ActiveRecord::Base,
# controller calls A.permit_attr(params)
# lots simpler than moving all attr_accessible definitions to controllers
# bug: fails if more than one attr_accessible statement

def (ActiveRecord::Base).attr_accessible *fields
  puts "attr_accessible:"+self.name+":permitted_params fields=#{fields.inspect}"
  define_singleton_method("permit_attr") { |params|
    # may have subclasses where attr_accessible is in superclass
    # thus must require by subclass name so should calculate require at runtime
    rq = self.name.downcase.to_sym
    puts "...permit_attr:self=#{rq} permit(#{fields.inspect})"
    params.require(rq).permit(fields)
  }

end

To protect against multiple attr_accessible declarations, before defining the method, add

raise "error: model can only have one attr_accessible declaration" if defined? permit_attr

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser2532974View Question on Stackoverflow
Solution 1 - Ruby on-RailsPierre-Louis GottfroisView Answer on Stackoverflow
Solution 2 - Ruby on-RailsedikgatView Answer on Stackoverflow
Solution 3 - Ruby on-Railsmiklki14567View Answer on Stackoverflow
Solution 4 - Ruby on-RailsHardik HardiyaView Answer on Stackoverflow
Solution 5 - Ruby on-RailsSidView Answer on Stackoverflow
Solution 6 - Ruby on-RailsLex LindseyView Answer on Stackoverflow