Thursday, February 17, 2011

Authlogic activation tutorial


Step 1

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

Step 2

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

Step 3

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

Step 4

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

Step 5

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 "noreply@binarylogic.com" # Removed name/brackets around 'from' to resolve "555 5.5.2 Syntax error." as of Rails 2.3.3
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 "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'


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.


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.action_mailer.default_url_options = {:host => "binarylogic.com"}

Step 6

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

1 comment:

  1. Your blog is in a convincing manner, thanks for sharing such an information with lots of your effort and time
    ruby on rails training
    ruby on rails training India
    ruby on rails training Hyderabad

    ReplyDelete