This tutorial is divided into a number of steps and walks through the process of implementing user activation functionality into your pre-existing Rails app using Authlogic. If you are just starting out with Authlogic, be sure to checkout the Authlogic Example Tutorial.
Just a reminder, the code, as is, may not work with the most recent versions of Authlogic!
Thanks to Clayton Lengel-Zigich for cleaning up the tutorial and making it easier to read!
Let’s begin by adding an ‘active’ field with a default of false to the user model.
script/generate migration AddActiveToUsers active:boolean
# new migration XXX_add_active_to_users.rb class AddActiveToUsers < ActiveRecord::Migration def self.up add_column :users, :active, :boolean, :default => false, :null => false end def self.down remove_column :users, :active end end
Don’t forget to run the migration.
rake db:migrate
Authlogic automatically executes the following methods, if present, upon user action: active?, approved?, and confirmed?. Since we added an active column, the “active?” method will be dynamically generated by ActiveRecord so we can hook into this magical goodness. And we should make sure that we protect the active attribute from mass-assignments by calling attr_accessible.
# added to user.rb attr_accessible :login, :email, :password, :password_confirmation, :openid_identifier
Now try to log in. You should receive the error, “Your account is not active.” So far so good. Let’s make a controller to handle our activations:
script/generate controller activations create
# new file app/controllers/activations_controller.rb class ActivationsController < ApplicationController before_filter :require_no_user def create @user = User.find_using_perishable_token(params[:activation_code], 1.week) || (raise Exception) raise Exception if @user.active? if @user.activate! flash[:notice] = "Your account has been activated!" UserSession.create(@user, false) # Log user in manually @user.deliver_welcome! redirect_to account_url else render :action => :new end end end
I raise exceptions in these actions to make sure that someone who is already active cannot re-activate their account and to deal with an invalid perishable token. I’ll leave it up to you how you want to handle these errors — you should probably provide some sort of “My Token is Expired!” action that will reset the token and resend the activation email if the user does not get around to activating right away.
Going down the list, let’s define the missing actions. First:
# added to user.rb def activate! self.active = true save end
Next, let’s make sure our user gets an e-mail with his activation code when he signs up. How are we getting our activation code? The same way we get our password reset code — through our perishable token:
# added to app/models/user.rb def deliver_activation_instructions! reset_perishable_token! Notifier.deliver_activation_instructions(self) end def deliver_welcome! reset_perishable_token! Notifier.deliver_welcome(self) end # added to app/models/notifier.rb def activation_instructions(user) subject "Activation Instructions" from "Binary Logic <noreply@binarylogic.com>" recipients user.email sent_on Time.now body :account_activation_url => activate_url(user.perishable_token) end def welcome(user) subject "Welcome to the site!" from "Binary Logic <noreply@binarylogic.com>" recipients user.email sent_on Time.now body :root_url => root_url end # added to config/routes.rb map.activate '/activate/:activation_code', :controller => 'activations', :action => 'create' <!-- new file app/views/notifier/activation_instructions.erb --> Thank you for creating an account! Click the url below to activate your account! <%= @account_activation_url %> If the above URL does not work try copying and pasting it into your browser. If you continue to have problem, please feel free to contact us. <!-- new file app/views/notifier/welcome.erb --> Welcome to the site! Your account has been activated. <%= @root_url %> If the above URL does not work try copying and pasting it into your browser. If you continue to have problem, please feel free to contact us.
Note: I got a “Missing host to link to! Please provide :host parameter or set default_url_options[:host]” error when I tried this, so if you do to you will have to set the default_url_options in your environment.rb or environment config.
<!-- config/environments/development.rb --> config.action_mailer.default_url_options = {:host => "binarylogic.com"}
Now let’s modify the user create action:
# modified app/controllers/users_controller.rb def create @user = User.new(params[:user]) # Saving without session maintenance to skip # auto-login which can't happen here because # the User has not yet been activated if @user.save_without_session_maintenance @user.deliver_activation_instructions! flash[:notice] = "Your account has been created. Please check your e-mail for your account activation instructions!" redirect_to root_url else render :action => :new end end
And that’s it! Let me know if you have any suggestions for improvement.