Strong Parameters and mass assignment
Fast recall
Quick revision
Core answer
Whether the learner understands permitted shape, mass assignment, nested input, and the authorization boundary.
Saying unpermitted params are silently mass-assigned or believing permit(:admin) is safe for every caller.
Explain ForbiddenAttributesError, expect, nested arrays, and role-specific permitted fields.
Interview-ready guide
Interview answer
Strong Parameters are Rails' controller boundary for mass assignment. Request data arrives as an unpermitted ActionController::Parameters object, so a controller cannot safely pass an arbitrary submitted hash straight to create or update. It must first name the keys and nested shapes that this endpoint accepts.
In current Rails, params.expect(user: [:name, :email]) requires the expected user shape and permits those fields. Existing applications commonly use params.require(:user).permit(:name, :email). Nested arrays and hashes need their own explicit shape; broad escapes such as permit!, {} permission, or to_unsafe_h remove much of this protection.
A submitted key is not safe merely because the model has that column. A profile endpoint can accept name, email, and time_zone without accepting admin or suspended. An administrator action can use a different parameter method after its own authorization check. This keeps a future sensitive column from silently entering every update path.
Strong Parameters filter shape; they do not prove that an email is valid or that this user may change a field. Authorization checks the actor and record, model and database validation protect value rules, and Strong Parameters limit what reaches mass assignment. I would test each boundary by submitting a sensitive key and proving that it stays unchanged.
Strong Parameters and mass assignment
Direct Answer
Strong Parameters require controller input to be explicitly permitted before Active Model mass assignment. Use params.expect in current Rails or require(...).permit(...) in established code to select the allowed shape, but still validate values and authorize which fields this particular user may change.
Deep Dive & Architecture
Rails collects query, body, and route data into an ActionController::Parameters object. It is intentionally marked unpermitted. Passing a nested unpermitted parameters object to Model.create or record.update raises ActiveModel::ForbiddenAttributesError; modern Rails does not simply assign every submitted column. This fail-closed behaviour is the foundation of Strong Parameters.
expect is the concise current API for requiring and permitting an expected shape. params.expect(user: [:name, :email]) requires user to be a suitable nested parameters hash and returns permitted values for the listed fields. The familiar require(:user).permit(:name, :email) remains widespread. Missing or malformed required structure is handled as a bad request rather than becoming a mysterious nil later.
Nested data needs an exact declaration. A scalar list uses an empty array marker, while nested objects list their own allowed keys. Permitting an empty hash accepts arbitrary keys and can automatically expose future model attributes, so it is not a shortcut for a schema that the application actually knows. permit! and to_unsafe_h similarly bypass the boundary and should be rare and reviewed.
The permitted list is endpoint-specific, not model-wide. A self-service update might permit display name and time zone; an administrator action might also permit suspension state after a separate policy check. Putting :admin in a shared user_params method would make mass assignment technically allowed even when the current caller has no authority. Strong Parameters cannot infer that business rule.
After filtering, model validations enforce type and domain constraints, database constraints protect persisted invariants, and authorization checks the actor and record. Request specs should submit an unexpected sensitive field and prove it remains unchanged, test missing and wrongly shaped roots, and cover each role's accepted fields. This makes the boundary observable and protects it when columns or nested forms are added later.
For APIs, distinguish an unknown field from a known field the caller cannot change. The response policy may reject unknown keys or ignore them for compatibility, but a sensitive attempted update should be observable without echoing secrets. Tests should document that decision consistently across endpoints.
Code Example
class UsersController < ApplicationController
def update
current_user.update!(profile_params)
redirect_to profile_path
end
private
def profile_params
params.expect(user: [:name, :email, :time_zone])
end
end
# A separate admin controller may permit :suspended after authorization.
The self-service endpoint has no mass-assignment path for admin or suspension fields.
Common Mistakes & Pitfalls
Saying unpermitted params are silently mass-assigned or believing permit(:admin) is safe for every caller.
Check your understanding
Answer these without looking back at the article.
- What happens when unpermitted Parameters reach update?
- How is params.expect different from require(...).permit(...)?
- Why are Strong Parameters not an authorization system?
Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.