Action Controller Parameters

Allows to choose which attributes should be whitelisted for mass updating and thus prevent accidentally exposing that which shouldn’t be exposed. Provides two methods for this purpose: require and permit. The former is used to mark parameters as required. The latter is used to set the parameter as permitted and limit which attributes should be allowed for mass updating.

params = ActionController::Parameters.new({
  person: {
    name: 'Francesco',
    age:  22,
    role: 'admin'
  }
})

permitted = params.require(:person).permit(:name, :age)
permitted            # => {"name"=>"Francesco", "age"=>22}
permitted.class      # => ActionController::Parameters
permitted.permitted? # => true

Person.first.update!(permitted)
# => #<Person id: 1, name: "Francesco", age: 22, role: "user">

It provides two options that controls the top-level behavior of new instances:

  • permit_all_parameters- If it's true, all the parameters will be permitted by default. The default is false.

  • action_on_unpermitted_parameters- Allow to control the behavior when parameters that are not explicitly permitted are found. The values can be :logto write a message on the logger or :raiseto raise ActionController::UnpermittedParameters exception. The default value is :login test and development environments, falseotherwise.

Examples:

params = ActionController::Parameters.new
params.permitted? # => false

ActionController::Parameters.permit_all_parameters = true

params = ActionController::Parameters.new
params.permitted? # => true

params = ActionController::Parameters.new(a: "123", b: "456")
params.permit(:c)
# => {}

ActionController::Parameters.action_on_unpermitted_parameters = :raise

params = ActionController::Parameters.new(a: "123", b: "456")
params.permit(:c)
# => ActionController::UnpermittedParameters: found unpermitted keys: a, b

ActionController::Parametersis inherited from ActiveSupport::HashWithIndifferentAccess, this means that you can fetch values using either :keyor "key".

params = ActionController::Parameters.new(key: 'value')
params[:key]  # => "value"
params["key"] # => "value"
Methods
#
D
F
N
P
R
S
Constants
NEVER_UNPERMITTED_PARAMS = %w( controller action )
 

Never raise an UnpermittedParameters exception because of these params are present. They are added by Rails and it's of no concern.

PERMITTED_SCALAR_TYPES = [ String, Symbol, NilClass, Numeric, TrueClass, FalseClass, Date, Time, # DateTimes are Dates, we document the type but avoid the redundant check. StringIO, IO, ActionDispatch::Http::UploadedFile, Rack::Test::UploadedFile, ]
 

This is a white list of permitted scalar types that includes the ones supported in XML and JSON requests.

This list is in particular used to filter ordinary requests, String goes as first element to quickly short-circuit the common case.

If you modify this collection please update the API of permit above.

EMPTY_ARRAY = []
 
Class Public methods
new(attributes = nil)

Returns a new instance of ActionController::Parameters. Also, sets the permittedattribute to the default value of ActionController::Parameters.permit_all_parameters.

class Person < ActiveRecord::Base
end

params = ActionController::Parameters.new(name: 'Francesco')
params.permitted?  # => false
Person.new(params) # => ActiveModel::ForbiddenAttributesError

ActionController::Parameters.permit_all_parameters = true

params = ActionController::Parameters.new(name: 'Francesco')
params.permitted?  # => true
Person.new(params) # => #<Person id: nil, name: "Francesco">
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 123
def initialize(attributes = nil)
  super(attributes)
  @permitted = self.class.permit_all_parameters
end
Instance Public methods
[](key)

Returns a parameter for the given key. If not found, returns nil.

params = ActionController::Parameters.new(person: { name: 'Francesco' })
params[:person] # => {"name"=>"Francesco"}
params[:none]   # => nil
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 271
def [](key)
  convert_hashes_to_parameters(key, super)
end
dup()

Returns an exact copy of the ActionController::Parameters instance. permittedstate is kept on the duped object.

params = ActionController::Parameters.new(a: 1)
params.permit!
params.permitted?        # => true
copy_params = params.dup # => {"a"=>1}
copy_params.permitted?   # => true
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 313
def dup
  super.tap do |duplicate|
    duplicate.instance_variable_set :@permitted, @permitted
  end
end
fetch(key, *args)

Returns a parameter for the given key. If the key can't be found, there are several options: With no other arguments, it will raise an ActionController::ParameterMissingerror; if more arguments are given, then that will be returned; if a block is given, then that will be run and its result returned.

params = ActionController::Parameters.new(person: { name: 'Francesco' })
params.fetch(:person)               # => {"name"=>"Francesco"}
params.fetch(:none)                 # => ActionController::ParameterMissing: param not found: none
params.fetch(:none, 'Francesco')    # => "Francesco"
params.fetch(:none) { 'Francesco' } # => "Francesco"
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 286
def fetch(key, *args)
  convert_hashes_to_parameters(key, super)
rescue KeyError
  raise ActionController::ParameterMissing.new(key)
end
permit(*filters)

Returns a new ActionController::Parametersinstance that includes only the given filtersand sets the permittedattribute for the object to true. This is useful for limiting which attributes should be allowed for mass updating.

params = ActionController::Parameters.new(user: { name: 'Francesco', age: 22, role: 'admin' })
permitted = params.require(:user).permit(:name, :age)
permitted.permitted?      # => true
permitted.has_key?(:name) # => true
permitted.has_key?(:age)  # => true
permitted.has_key?(:role) # => false

Only permitted scalars pass the filter. For example, given

params.permit(:name)

:namepasses it is a key of paramswhose associated value is of type String, Symbol, NilClass, Numeric, TrueClass, FalseClass, Date, Time, DateTime, StringIO, IO, +ActionDispatch::Http::UploadedFile+ or +Rack::Test::UploadedFile+. Otherwise, the key :nameis filtered out.

You may declare that the parameter should be an array of permitted scalars by mapping it to an empty array:

params = ActionController::Parameters.new(tags: ['rails', 'parameters'])
params.permit(tags: [])

You can also use permiton nested parameters, like:

params = ActionController::Parameters.new({
  person: {
    name: 'Francesco',
    age:  22,
    pets: [{
      name: 'Purplish',
      category: 'dogs'
    }]
  }
})

permitted = params.permit(person: [ :name, { pets: :name } ])
permitted.permitted?                    # => true
permitted[:person][:name]               # => "Francesco"
permitted[:person][:age]                # => nil
permitted[:person][:pets][0][:name]     # => "Purplish"
permitted[:person][:pets][0][:category] # => nil

Note that if you use permitin a key that points to a hash, it won't allow all the hash. You also need to specify which attributes inside the hash should be whitelisted.

params = ActionController::Parameters.new({
  person: {
    contact: {
      email: 'none@test.com',
      phone: '555-1234'
    }
  }
})

params.require(:person).permit(:contact)
# => {}

params.require(:person).permit(contact: :phone)
# => {"contact"=>{"phone"=>"555-1234"}}

params.require(:person).permit(contact: [ :email, :phone ])
# => {"contact"=>{"email"=>"none@test.com", "phone"=>"555-1234"}}
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 248
def permit(*filters)
  params = self.class.new

  filters.flatten.each do |filter|
    case filter
    when Symbol, String
      permitted_scalar_filter(params, filter)
    when Hash then
      hash_filter(params, filter)
    end
  end

  unpermitted_parameters!(params) if self.class.action_on_unpermitted_parameters

  params.permit!
end
permit!()

Sets the permittedattribute to true. This can be used to pass mass assignment. Returns self.

class Person < ActiveRecord::Base
end

params = ActionController::Parameters.new(name: 'Francesco')
params.permitted?  # => false
Person.new(params) # => ActiveModel::ForbiddenAttributesError
params.permit!
params.permitted?  # => true
Person.new(params) # => #<Person id: nil, name: "Francesco">
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 150
def permit!
  each_pair do |key, value|
    convert_hashes_to_parameters(key, value)
    self[key].permit! if self[key].respond_to? :permit!
  end

  @permitted = true
  self
end
permitted?()

Returns trueif the parameter is permitted, false otherwise.

params = ActionController::Parameters.new
params.permitted? # => false
params.permit!
params.permitted? # => true
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 134
def permitted?
  @permitted
end
require(key)

Ensures that a parameter is present. If it's present, returns the parameter at the given key, otherwise raises an ActionController::ParameterMissingerror.

ActionController::Parameters.new(person: { name: 'Francesco' }).require(:person)
# => {"name"=>"Francesco"}

ActionController::Parameters.new(person: nil).require(:person)
# => ActionController::ParameterMissing: param not found: person

ActionController::Parameters.new(person: {}).require(:person)
# => ActionController::ParameterMissing: param not found: person
Also aliased as: required
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 172
def require(key)
  self[key].presence || raise(ParameterMissing.new(key))
end
required(key)

Alias of require.

Alias for: require
slice(*keys)

Returns a new ActionController::Parametersinstance that includes only the given keys. If the given keys don't exist, returns an empty hash.

params = ActionController::Parameters.new(a: 1, b: 2, c: 3)
params.slice(:a, :b) # => {"a"=>1, "b"=>2}
params.slice(:d)     # => {}
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 299
def slice(*keys)
  self.class.new(super).tap do |new_instance|
    new_instance.instance_variable_set :@permitted, @permitted
  end
end