Rails: Accessing strong parameters

Posted . Visible to the public.

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.

Last edit
Dominik Schöler
License
Source code in this card is licensed under the MIT License.
Posted by Emanuel to makandra dev (2025-01-27 10:53)