instance method
permit
Ruby on Rails 8.1.2
Since v4.0.13Signature
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: "none@test.com", phone: "555-1234" } } }) params.permit(person: :contact).require(:person) # => ActionController::ParameterMissing: param is missing or the value is empty or invalid: person 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"=>"none@test.com", "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: "none@test.com", phone: "555-1234" }, '1': { email: "nothing@test.com", phone: "555-6789" }, } }) params.permit(person: [:email]).to_h # => {"person"=>{"0"=>{"email"=>"none@test.com"}, "1"=>{"email"=>"nothing@test.com"}}}
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: "none@test.com", phone: "555-1234" }, '1': { email: "nothing@test.com", phone: "555-6789" }, } }) params.permit(person: { '0': [:email], '1': [:phone]}).to_h # => {"person"=>{"0"=>{"email"=>"none@test.com"}, "1"=>{"phone"=>"555-6789"}}}
Parameters
-
filtersrest
Source
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 668
def permit(*filters)
permit_filters(filters, on_unpermitted: self.class.action_on_unpermitted_parameters, explicit_arrays: false)
end
Defined in actionpack/lib/action_controller/metal/strong_parameters.rb line 668
· View on GitHub
· Improve this page
· Find usages on GitHub
Defined in ActionController::Parameters