method

permit

permit(*filters)
public

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"}}}