Challenge 3: A Careful Callback — Solution class User < ApplicationRecord before_save :downcase_email private def downcase_email self.email = email.downcase end end # Why this callback is safe/appropriate: # downcase_email only transforms data that already belongs to the record # being saved -- it has no effect outside this one User instance, sends # no messages, triggers no other systems, and produces no side effect a # developer reading "user.save" elsewhere in the codebase would need to # know about in advance. It's pure data normalization, entirely # self-contained. # # Why a callback like sending a welcome email would be risky by # comparison: # An after_create :send_welcome_email callback means every single place # in the codebase that calls User.create or user.save (a controller, a # database seed script, a test setup helper, an admin console command) # would silently trigger a real email send -- a side effect entirely # invisible at the call site, unlike an explicit # UserMailer.welcome(user).deliver_later line written directly inside the # specific controller action where a new signup actually happens. =begin Notes: - The chapter's line between "safe" and "risky" callbacks isn't about before_save vs after_create specifically -- it's about whether the callback only prepares the record's own data (safe) versus reaches outside the record to affect something else, like sending an email, charging a payment, or notifying another service (risky). - downcase_email would run on every single save, including updates where nothing about the email actually changed -- which is fine here since it's idempotent (downcasing an already-lowercase email changes nothing), but is worth noting as a property a "safe" callback should generally have. =end