Strong Parameters
When a member submits the "new book" form, Rails collects every field into params. It is tempting to hand the whole thing to the model. But anyone can add extra fields to a request with their browser's developer tools, and a model will happily set any attribute it is given. Strong parameters close that door.
The rule
params is untrusted: permit by name, pass only what you permit.
params holds everything from the URL, the query string and the form body. A form built for a book nests its fields under book:
# params for POST /books
{ "book" => { "title" => "Dune", "pages" => "412", "featured" => "true" },
"controller" => "books", "action" => "create" }Passing params[:book] straight to Book.new raises ActiveModel::ForbiddenAttributesError. You must say which keys are allowed:
class BooksController < ApplicationController
def create
@book = Book.new(book_params)
# ...
end
private
def book_params
params.expect(book: [:title, :author, :pages]) # Rails 8
# params.require(:book).permit(:title, :author, :pages) # Rails 7 style, still works
end
endrequire(:book)/expect(book: ...)— thebookkey must be present, or Rails answers400 Bad Request.- The listed fields are kept; anything else (here
featured) is dropped.
Arrays and nested hashes need their shape spelled out: genre_ids: [] for a list of ids, or address: [:city, :zip] for a nested hash.
Values in params are always strings ("412"). The model converts them to the column's type when it assigns them.
The shortcut
For every form, write one private *_params method listing the fields a member is allowed to change, and use only that method in create and update. Anything sensitive — admin, role, prices, owner ids — stays off the list and is set in code instead.
The attack
A member edits the form in the browser and adds
book[featured]=true.
The trap is permitting a field "to make the error go away". Every name you add is a promise that any user may set it.
Drills
Answer fast — trust the rule.
What happens with Book.new(params[:book]) when nothing has been permitted?
With permit(:title, :pages), the request also contains book[price]. What happens to price?
Which field should NOT be in member_params for a public sign-up form?
How do you permit an array of genre ids?
What type is params[:book][:pages] when the form sends 412?
Remember
- params is untrusted: permit by name, pass only what you permit.
- Shortcut: one private
*_paramsmethod per form, used by create and update. - Trap: permitting sensitive fields to silence the error.
