permit
permit(*filters)Returns a new `ActionController::Parameters` instance that includes only the given `filters` and sets the `permitted` attribute for the object to `true`. This is useful for limiting which attributes should be allowed for mass updating.
params = ActionController::Parameters.new(name: "Francesco", age: 22, role: "admin") permitted = params.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)
`:name` passes if it is a key of `params` whose 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 `:name` is 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: [])
Sometimes it is not possible or convenient to declare the valid keys of a hash parameter or its internal structure. Just map to an empty hash:
params.permit(preferences: {})
Be careful because this opens the door to arbitrary input. In this case, `permit` ensures values in the returned structure are permitted scalars and filters out anything else.
You can also use `permit` on nested parameters:
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
This has the added benefit of rejecting user-modified inputs that send a string when a hash is expected.
When followed by `require`, you can both filter and require parameters following the typical pattern of a Rails form. The `expect` method was made specifically for this use case and is the recommended way to require and permit parameters.
permitted = params.expect(person: [:name, :age])
When using `permit` and `require` separately, pay careful attention to the order of the method calls.
params = ActionController::Parameters.new(person: { name: "Martin", age: 40, role: "admin" }) permitted = params.permit(person: [:name, :age]).require(:person) # correct
When require is used first, it is possible for users of your application to trigger a NoMethodError when the user, for example, sends a string for :person.
params = ActionController::Parameters.new(person: "tampered") permitted = params.require(:person).permit(:name, :age) # not recommended # => NoMethodError: undefined method `permit' for an instance of String
Note that if you use `permit` in 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 permitted.
params = ActionController::Parameters.new({ person: { contact: { email: "[email protected]", phone: "555-1234" } } }) params.permit(person: :contact).require(:person) # => #<ActionController::Parameters {} permitted: true> params.permit(person: { contact: :phone }).require(:person) # => #<ActionController::Parameters {"contact"=>#<ActionController::Parameters {"phone"=>"555-1234"} permitted: true>} permitted: true> params.permit(person: { contact: [ :email, :phone ] }).require(:person) # => #<ActionController::Parameters {"contact"=>#<ActionController::Parameters {"email"=>"[email protected]", "phone"=>"555-1234"} permitted: true>} permitted: true>
If your parameters specify multiple parameters indexed by a number, you can permit each set of parameters under the numeric key to be the same using the same syntax as permitting a single item.
params = ActionController::Parameters.new({ person: { '0': { email: "[email protected]", phone: "555-1234" }, '1': { email: "[email protected]", phone: "555-6789" }, } }) params.permit(person: [:email]).to_h # => {"person"=>{"0"=>{"email"=>"[email protected]"}, "1"=>{"email"=>"[email protected]"}}}
If you want to specify what keys you want from each numeric key, you can instead specify each one individually
params = ActionController::Parameters.new({ person: { '0': { email: "[email protected]", phone: "555-1234" }, '1': { email: "[email protected]", phone: "555-6789" }, } }) params.permit(person: { '0': [:email], '1': [:phone]}).to_h # => {"person"=>{"0"=>{"email"=>"[email protected]"}, "1"=>{"phone"=>"555-6789"}}}