Rails wraps your parameters into an interface called StrongParameters Show archive.org snapshot . In most cases, your form submits your data in a nested structure which goes hand in hand with the strong parameters interface.
Example:
curl -X POST -d "user[name]=bob" https://example.com/users
class UsersController
def create
User.create!(params.expect(user: [:name])) # Or User.create!(params.require(:user).permit(:name))
end
end
This works well most of the time. However, there are cases where this does not fit your use case, or has side effects.
If you do it differently, be extra careful not to introduce security issues.
Use expect
/ permit
/ require
by default
Generally, it's advised to use expect
/permit
/require
when passing them to e.g. ActiveRecord. Note that expect
is only available from Rails 8.
There are cases where it might be fine to read directly, like:
# Okay
User.find(params[:id])
This still relies on params[:id]
existing, so your code should reflect that:
# Better
User.find(params.expect(:id)) # Or User.find(params.require(:id))
Avoiding issues with extra parameters
Rails logs extra params in development.
This can be annoying when you have extra params, like page=2
.
Or, your application may even be configured with config.action_controller.action_on_unpermitted_parameters = :raise
and you want to allow such extra params in some cases.
# Problematic example
redirect_to users_path(params.permit(:query, :encoding)) # but params also contains page=2
You should still use permit
(or expect
) to receive Strong Parameters, but strip extra parameters.
# Better (option 1)
redirect_to users_path(params.slice(:query, :encoding).permit(:query, :encoding))
# Better (option 2)
redirect_to users_path(params.except(:page).permit(:query, :encoding))
Do not use permit!
to allow all parameters
Do not use permit!
.
# Dangerous!
User.create!(params.permit!)
We have an extra card on why you should not do this and possible alternatives.
Do not pass all params into url_for
Do not use url_for
with params
directly.
# Dangerous!
url_for(params.to_unsafe_h)`
We have an extra card on this topic.
Further reading
It's also worth to read Rails: Using require and permit for attributes when configuring your application.