Passwords and More Security for a Rails Ecommerce Application
In this third part to a four-part series on building the security into a Ruby-on-Rails ecommerce application, we'll focus on the changes we need to make to the program so that users can change their passwords. This article is excerpted from chapter eight of the book Practical Rails Projects, written by Eldon Alameda (Apress; ISBN: 1590597818).
Passwords and More Security for a Rails Ecommerce Application - Using Observers (Page 3 of 4 )
When we createdUserNotifierin the beginning of the Reset Password user story implementation, the generator also created a file calleduser_observer.rbinapp/models. Observers in Rails are classes that monitor the life cycle of ActiveRecord objects, somewhat similar to the filters for controllers. Observers support the following callback methods:
after_create
after_destroy
after_save
after_update
after_validation
after_validation_on_create
after_validation_on_update
before_create
before_destroy
before_save
before_update
before_validation
before_validation_on_create
before_validation_on_update
You can call these callbacks directly in an ActiveRecord model, too:
class MyModel < ActiveRecord::Base after_save :say_foo
def say_foo logger.info "Foo-oo!" end end
However, if your callback code gets longer and/or you want to implement similar behavior for multiple models, it’s a good idea to extract the callbacks to an observer. Observers also give you more flexibility, since you can restrict the callbacks to happen only in certain controllers, as we will do in this section.
When thegenerate authenticated_mailer usercommand created theUserObserver observer, it created two callbacks for it:
class UserObserver < ActiveRecord::Observer def after_create(user) UserNotifier.deliver_signup_notification(user) end
def after_save(user) UserNotifier.deliver_activation(user) if user.recently_activated? end end
However, we don’t need either of these callbacks, since we aren’t implementing signup notification or user activation in this sprint. We can simplify the observer to look like this:
class UserObserver < ActiveRecord::Observer def after_save(user) UserNotifier.deliver_forgot_password(user) if user.password_forgotten end end
You might have wondered what we’re going to do with the@password_forgottenvariable in theUserclass, and here’s the answer. Ourafter_savemethod inUserObserverkicks in when theUser object is saved and checks whether the variable istrue. If yes, it asks theUserNotifiermailer to deliver theforgot_passwordmail, passing the current user as an attribute. In normal cases, when@password_forgottenisnil, the observer does nothing.