Search code examples
ruby-on-railsrubystrong-parameters

Rails 5 - Forbidden Attributes


Rails is throwing an error when attempting to create when I have added all the attributes to the necessary function and referenced it in the right places (as far as I am aware). Can sucessfuly update. It is happening accross multiple controllers, unfortunately. I assume the problem is the same for all of them.

This is part of an upgrade to rails 5, previously rails 2. Ruby version: 2.6.3

Create function:

def create
    @shipment_method = ShipmentMethod.new(shipment_methods_params)
    respond_to do |format|
      if @shipment_method.save
        format.html { redirect_to shipment_methods_url, notice: 'Shipment method was successfully created.' }
        format.json { render json: @shipment_method, status: :created, location: @shipment_method }
      else
        format.html { render action: "new" }
        format.json { render json: @shipment_method.errors, status: :unprocessable_entity }
      end
    end
  end

Params function:

def shipment_methods_params
    params.require(:shipment_method).permit(:name, :description, :shipping_url, :active, :supports_tracking, :requires_phone)
  end

Request params:

Request parameters  
{"utf8"=>"✓", "authenticity_token"=>"KjPFsCA5xwgeIx4U3eOH4sA1IuYY5FSw6kvK16XyyKarEzlxSi6N04LFBdsJHWyIwt+ujv6gz9D+flYBeJ+pWA==", "shipment_method"=>{"name"=>"1", "description"=>"1", "shipping_url"=>"1", "active"=>"0", "supports_tracking"=>"0", "requires_phone"=>"0"}, "commit"=>"Create Shipment method", "controller"=>"shipment_methods", "action"=>"create"}

Server log for the request:

Processing by ShipmentMethodsController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"KjPFsCA5xwgeIx4U3eOH4sA1IuYY5FSw6kvK16XyyKarEzlxSi6N04LFBdsJHWyIwt+ujv6gz9D+flYBeJ+pWA==", "shipment_method"=>{"name"=>"1", "description"=>"1", "shipping_url"=>"1", "active"=>"0", "supports_tracking"=>"0", "requires_phone"=>"0"}, "commit"=>"Create Shipment method"}
  User Load (0.6ms)  SELECT  `users`.* FROM `users` WHERE `users`.`id` = 5 ORDER BY `users`.`id` ASC LIMIT 1
Completed 500 Internal Server Error in 4ms (ActiveRecord: 0.6ms)



ActiveModel::ForbiddenAttributesError - ActiveModel::ForbiddenAttributesError:

Full class:

class ShipmentMethod < ActiveRecord::Base
  # public :description, :active, :name, :requires_phone, :supports_tracking, :shipping_url

  ## Associations
  has_many :shipments

  ## Validations
  validates :name, presence: true, uniqueness: true

  ## Scopes
  default_scope -> {order(:name)}
  scope :active, -> {where("active = 1")}
end

Solution

  • If there is a load_and_authorize_resource before action in your controllers, what is happening is that method is taking your parameters and attempting to create an instance before it ever gets to the method. Hence it ignores the strong parameters you have created.

    So, of course, it never reaches the method and BAM -- the dreaded FAE.

    One remedy is to tweak the before actions...

      load_and_authorize_resource :shipment_method, except: [:create]
      authorize_resource :shipment_method, only: [:create] 
    

    But that is very dull.

    The other is to change the name of your strong parameters method to shipment_method_params...

    def shipment_method_params
        params.require(:shipment_method).permit(:name, :description, :shipping_url, :active, :supports_tracking, :requires_phone)
      end
    

    Because, Rails and its love of conventions. You can also make separate create_params and update_params if you have different parameters for those actions.