forked from rails/rails
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
b0d378a
commit 6c206f6
Showing
3 changed files
with
74 additions
and
24 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -315,49 +315,99 @@ but 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. | ||
|
||
To permit an entire hash of parameters, the [`permit!`][] method can be | ||
used: | ||
[`expect`][] provides a concise and safe way to require and permit parameters. | ||
|
||
```ruby | ||
params.require(:log_entry).permit! | ||
id = params.expect(:id) | ||
``` | ||
|
||
`expect` ensures that the type returned is not vulnerable to param tampering. | ||
The above expect will always return a scalar value and not an array or hash. | ||
When expecting params from a form, use `expect` to ensure that the root key | ||
is present and the attributes are permitted. | ||
|
||
```ruby | ||
user_params = params.expect(user: [:username, :password]) | ||
user_params.has_key?(:username) # => true | ||
``` | ||
|
||
`expect` will raise the an error and return a 400 Bad Request response | ||
when the user key is not a nested hash with the expected keys. | ||
|
||
When a param is optional but needs to be permitted if it's present, use | ||
[`allow`][] to do both in a single step: | ||
|
||
```ruby | ||
new_user = params.allow(user: [:name, :email]) | ||
# => {} if params[:user] is not a hash of parameters. | ||
``` | ||
|
||
To require and permit an entire hash of parameters, [`expect`][] can be | ||
used in this way (substitute `allow` if the params are optional): | ||
|
||
```ruby | ||
params.expect(log_entry: {}) | ||
``` | ||
|
||
This marks the `:log_entry` parameters hash and any sub-hash of it as | ||
permitted and does not check for permitted scalars, anything is accepted. | ||
Extreme care should be taken when using `permit!`, as it will allow all current | ||
and future model attributes to be mass-assigned. | ||
Extreme care should be taken when using [`permit!`][] or calling `expect` | ||
with an empty hash, as it will allow all current and future model | ||
attributes to be mass-assigned with external user-controlled params. | ||
|
||
[`permit`]: https://api.rubyonrails.org/classes/ActionController/Parameters.html#method-i-permit | ||
[`permit!`]: https://api.rubyonrails.org/classes/ActionController/Parameters.html#method-i-permit-21 | ||
[`expect`]: https://api.rubyonrails.org/classes/ActionController/Parameters.html#method-i-expect | ||
[`allow`]: https://api.rubyonrails.org/classes/ActionController/Parameters.html#method-i-allow | ||
|
||
#### Nested Parameters | ||
|
||
You can also use `permit` on nested parameters, like: | ||
You can also use `expect` (or `permit` or `allow`) on nested parameters, like: | ||
|
||
```ruby | ||
params.permit(:name, { emails: [] }, | ||
friends: [ :name, | ||
{ family: [ :name ], hobbies: [] }]) | ||
# Given the example expected params: | ||
params = ActionController::Parameters.new( | ||
name: "Martin", | ||
emails: ["[email protected]"], | ||
friends: [ | ||
{ name: "André", family: { name: "RubyGems" }, hobbies: ["keyboards", "card games"] }, | ||
{ name: "Kewe", family: { name: "Baroness" }, hobbies: ["video games"] }, | ||
] | ||
) | ||
# the following expect will ensure the params are permitted | ||
name, emails, friends = params.expect( | ||
:name, # permitted scalar | ||
emails: [], # array of permitted scalars | ||
friends: [[ # array of permitted Parameter hashes | ||
:name, # permitted scalar | ||
{ | ||
family: [:name], # family: { name: "permitted scalar" } | ||
hobbies: [] # array of permitted scalars | ||
} | ||
]] | ||
) | ||
|
||
``` | ||
|
||
This declaration permits the `name`, `emails`, and `friends` | ||
attributes. It is expected that `emails` will be an array of permitted | ||
scalar values, and that `friends` will be an array of resources with | ||
specific attributes: they should have a `name` attribute (any | ||
permitted scalar values allowed), a `hobbies` attribute as an array of | ||
permitted scalar values, and a `family` attribute which is restricted | ||
to having a `name` (any permitted scalar values allowed here, too). | ||
This declaration permits the `name`, `emails`, and `friends` attributes and | ||
returns them each. It is expected that `emails` will be an array of permitted | ||
scalar values, and that `friends` will be an array of resources (note the new | ||
double array syntax to explicitly require an array) with specific | ||
attributes: they should have a `name` attribute (any permitted scalar values | ||
allowed), a `hobbies` attribute as an array of permitted scalar values, and a | ||
`family` attribute which is restricted to a hash with only a `name` key and | ||
any permitted scalar value. | ||
|
||
#### More Examples | ||
|
||
You may want to also use the permitted attributes in your `new` | ||
action. This raises the problem that you can't use [`require`][] on the | ||
root key because, normally, it does not exist when calling `new`: | ||
root key because, normally, it does not exist when calling `new`. | ||
Using `allow` for optional parameters permits them when present, but | ||
ignores them, returning an empty hash, when they are absent. | ||
|
||
```ruby | ||
# using `fetch` you can supply a default and use | ||
# the Strong Parameters API from there. | ||
params.fetch(:blog, {}).permit(:title, :author) | ||
params.allow(blog: [:title, :author]) | ||
``` | ||
|
||
The model class method `accepts_nested_attributes_for` allows you to | ||
|
@@ -366,7 +416,7 @@ parameters: | |
|
||
```ruby | ||
# permit :id and :_destroy | ||
params.expect(author: [:name, { books_attributes: [:title, :id, :_destroy] }]) | ||
params.expect(author: [:name, { books_attributes: [[:title, :id, :_destroy]] }]) | ||
``` | ||
|
||
Hashes with integer keys are treated differently, and you can declare | ||
|
@@ -380,7 +430,7 @@ with a `has_many` association: | |
# "chapters_attributes" => { "1" => {"title" => "First Chapter"}, | ||
# "2" => {"title" => "Second Chapter"}}}} | ||
|
||
params.expect(book: [:title, { chapters_attributes: [:title] }]) | ||
params.expect(book: [:title, { chapters_attributes: [[:title]] }]) | ||
``` | ||
|
||
Imagine a scenario where you have parameters representing a product | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters