Activation Emails with Restful Authentication and Acts_As_State_Machine
Update: December 18, 2007: less code, same result
Summary
If you use the Restful Authentication plugin with the –include-activation and –stateful options (see Acts_As_State_Machine and the post by Jonathan Linowes which united the two plugins), you’ll need to make a couple modifications to the code after you run the generator in order to keep the user activation email from being sent simultaneously with the user signup notification email.
Problem
The UserObserver code sends an activation email during the after_save callback if the user’s state is “pending.” Without activation the state transition goes from pending to active and we can leave the code alone. With activation, however, we introduce another state: the “state of being notified that our account has been created.”
If we change the UserObserver to watch for an “active” state instead of “pending,” the user will receive an activation email every time we save the user’s record and that puts the user into the state of “I’m about to adios this annoying website.”
Suggested Solution
We add a temporary state “notified” between pending and active that allows us to send the activation email at the right time with little disruption to the original restful authentication code.
Just before we “activate!” the user in the UserController, we “notify!” them, putting them in the “notified” state, save the user, which calls the after_save callback, which sends the activation email, and then return control to the UserController, which calls “activate!,” putting the user in the “active” state.
The Code
Changes to User.rb
Update: I removed the :do_notify code which was redundant (state transitions automatically save the record)
state :notified event :notify do transitions :from => :pending, :to => :notified end event :activate do transitions :from => :notified, :to => :active end event :suspend do transitions :from => [:passive, :pending, :notified, :active], :to => :suspended end event :delete do transitions :from => [:passive, :pending, :notified, :active, :suspended], :to => :deleted end
Changes to User_Observer.rb
def after_save(user) UserMailer.deliver_activation(user) if user.notified? end
Changes to User_Controller.rb
# In the activate method, # insert the notify! line right before the activate! line current_user.notify! current_user.activate!
If I’ve left something out, or if you have a better solution, please say so below. Cheers!
