What is `params.require(:person).permit(:name, :age)` doing in Rails 4?
Ruby on-Rails-4Ruby on-Rails-4 Problem Overview
All the examples of strong parameters in Rails 4 docs use
params.require(:person).permit(:name, :age)
Could someone please deconstruct and explain what is occurring with require
and permit
here?
Ruby on-Rails-4 Solutions
Solution 1 - Ruby on-Rails-4
The params
in a controller looks like a Hash, but it's actually an instance of ActionController::Parameters
, which provides several methods such as require
and permit
.
The require
method ensures that a specific parameter is present, and if it's not provided, the require
method throws an error. It returns an instance of ActionController::Parameters
for the key passed into require
.
The permit
method returns a copy of the parameters object, returning only the permitted keys and values. When creating a new ActiveRecord model, only the permitted attributes are passed into the model.
It looks a lot like the whitelisting that was formerly included in ActiveRecord models, but it makes more sense for it to be in the controller.
Solution 2 - Ruby on-Rails-4
To be more precise, when you create for eg. doing .new(...)
, there must be :person
hash indicated by require and the person hash will only accept :name
and :age
indicated by permit.
Example:
.new(person: { name: "Bhojendra", age: 32 }) // okay
.new(person: { name: "Rauniyar" }) // okay
.new(person: { name: "Bhojendra", other: 'asdf' }) // not okay, other not permitted
.new(person: { full_name: "Bhojendra Rauniyar" }) // not okay, full_name not permitted
.new(detail: { name: "Bhojendra", age: 32 }) // not okay, must be person
Solution 3 - Ruby on-Rails-4
Think of require
as validation and permit
as filtering.
require
will return the params under the given key if present, or raisepermit
will return the params filtered on the given keys*
Examples based on https://apidock.com/rails/ActionController/Parameters/permit
>> params = ActionController::Parameters.new(user: { name: "Francesco", age: 22, role: "admin" })
{
"user" => {
"name" => "Francesco",
"age" => 22,
"role" => "admin"
}
}
>> params.require(:user).permit(:name, :age)
Unpermitted parameter: role
{
"name" => "Francesco",
"age" => 22
}
>> params.require(:user)
{
"name" => "Francesco",
"age" => 22,
"role" => "admin"
}
>> params.require(:user).permit(:foo)
Unpermitted parameters: name, age, role
{}
>> params.require(:person)
ActionController::ParameterMissing: param is missing or the value is empty: person
>> params.permit(:user)
Unpermitted parameter: user
{}
* Note that permit
only allows certain scalars to pass the filter, as seen in the last example. The associated data must be of type String
, Symbol
, NilClass
, Numeric
, TrueClass
, FalseClass
, Date
, Time
, DateTime
, StringIO
, IO
, ActionDispatch::Http::UploadedFile
or Rack::Test::UploadedFile
. Everything else, including containers like Array
and Hash
, are filtered out.