Validations
A member submits a review with no rating and a body of "ok". Should it be saved? Validations are the model's answer. They live in one place, so every controller, console session and background job that saves a review obeys the same rules.
The rule
Declare the rules on the model; save says yes or no, errors say why.
class Review < ApplicationRecord
belongs_to :book
belongs_to :member
validates :rating, numericality: { only_integer: true, in: 1..5 }
validates :body, presence: true, length: { minimum: 10 }
validates :member_id, uniqueness: { scope: :book_id,
message: "has already reviewed this book" }
endCommon built-in validators:
presence: true— not nil or blanklength: { minimum:, maximum:, in: }numericality:— a number, with options likegreater_than:oronly_integer:inclusion: { in: [...] }— one of a fixed setformat: { with: /regex/ }uniqueness:— no other row has this value (optionally within ascope:)
What happens when rules fail:
review = Review.new(rating: 7, body: "ok")
review.valid? # => false
review.save # => false, nothing written
review.errors.full_messages # => ["Book must exist", "Member must exist",
# "Rating must be in 1..5",
# "Body is too short (minimum is 10 characters)"]
review.save! # raises ActiveRecord::RecordInvalidsave, create and update return true or false (create returns the object; check persisted?). Their bang twins save!, create!, update! raise instead. Use the plain ones in controllers, where a failure is expected and shown to the user, and the bang ones in scripts and seeds, where a failure should be loud.
A few methods skip validations entirely: update_column, update_columns, update_all, insert_all and save(validate: false). Use them only when you mean it.
The shortcut
For every attribute ask "must it exist, how big, what shape, and can it repeat?" The four answers map to presence, length or numericality, format or inclusion, and uniqueness.
Must it exist?
Yes:
presence: true.
The trap is trusting uniqueness alone. Two requests at the same moment can both pass the check. Back it with a unique index in a migration.
Drills
Answer fast — trust the rule.
A book fails validation. What does book.save return?
Which call raises ActiveRecord::RecordInvalid for an invalid review?
Which validation allows a member one review per book but many reviews across books?
Which method changes a column WITHOUT running validations?
Remember
- Declare the rules on the model; save says yes or no, errors say why.
- Shortcut: exist, size, shape, repeat.
- Trap: uniqueness without a unique index, and methods that skip validation.
