Restful_authentication & Activation

August 21, 2007 @ 06:06 PM | posted by carmelyne

(last updated: 06.04.08)

Extension of Railscasts Episode 67


============================

Update: [March 12, 2008] This blog post is outdated so if you found this page using google, I'd recommend reading something more up-to-date. Unfortunately, I don't know where else to refer you right now. I shared my thoughts and experience with the plugin at the time I was using it for a project. Living in the now, you can grab Obie Fernandez's Book "The Rails Way". That comes highly recommended!

============================

Ryan showed us how to set up restful_authentication a plugin by Rick Olson with his 67th Railscasts Episode: restful_authentication. Pretty awesome! Now, we will extend it to the activation part.

./script/generate authenticated user sessions --include-activation

With the added --include-activation option, more files and codes will be generated to handle "Activation for a User who just registered".

Shall we break them down in steps... baby steps and with codes. I would be happy to do a screencast for this but I dont own a podcast mic yet so lets do it the old school way. I know we're all spoiled by Ryan's RailsCasts and Geoffrey's PeepCodes. We are the little Brats! :)

After generating the files for restful_authentication, follow the 67th episode set up plus these...

Step 1: All about Environment.rb

Open your environment.rb file and set up the following:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# First, specify the Host that we will be using later for user_notifier.rb
HOST = 'http://www.yourrailsapp.com'

# Second, add the :user_observer
Rails::Initializer.run do |config|
  # The user observer goes inside the Rails::Initializer block
  config.active_record.observers = :user_observer
end

# Third, add your SMTP settings
ActionMailer::Base.delivery_method = :smtp
ActionMailer::Base.smtp_settings = {
  :address => "mail.yourrailsapp.com",
  :port => 25,
  :domain => "mail.yourrailsapp.com",
  :user_name => "carmelyne@yourrailsapp.com",
  :password => "yourrailsapp",
  :authentication => :login
}

Note: Just a heads up -- if you're on SliceHost like I am, I can't get this to work on just Postfix on Ubuntu. I needed to set up the SMTP settings on the environment.rb file.

Step 2: All about app/models/user_notifier.rb

Now you can see how we set a dryer way to add the HOST via #{HOST}. The codes below is also an example if you've extended it to handle resetting the passwords. Although you will have to add an additional user migration for "password_reset_code" and adding it to your user model/controller codes and more to your routes....
Anyway, code snippets below:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
class UserNotifier < ActionMailer::Base
  def signup_notification(user)
    setup_email(user)
    @subject    += 'Please activate your new account'  
    @body[:url]  = "#{HOST}/activate/#{user.activation_code}"
  
  end
  
  def activation(user)
    setup_email(user)
    @subject    += 'Your account has been activated!'
    @body[:url]  = "Visit #{HOST}!"
  end
  
  def forgot_password(user)
    setup_email(user)
    @subject    += 'You have requested to change your password'
    @body[:url]  = "#{HOST}/reset_password/#{user.password_reset_code}" 
  end

  def reset_password(user)
    setup_email(user)
    @subject    += 'Your password has been reset.'
  end   
  
  protected
    def setup_email(user)
      @recipients  = "#{user.email}"
      @from        = %("/Poke by carmelyne" <CT@yourrailsapp.com>) # Sets the User FROM Name and Email
      @subject     = "[YourRailsApp] "
      @sent_on     = Time.now
      @body[:user] = user
    end
end

Step 3: All about app/views/user_notifier/activation.rhtml

This gets sent out for the activation email so you can change the verbiage to something like this:

1
2
3
4
5
Thank you!

<%= @user.login %>, your account has been activated.  You may now start using the member only features.

<%= @url %>

I think that should be it. :)

I wrote this up to give you an idea for activation. If you extended it way beyond for forgot_password/reset_password, make sure you extend your user model and controller to handle these additional functions. More snippets....

Extras

1
2
3
# more for routes
map.forgot_password '/forgot_password', :controller => 'users', :action => 'forgot_password'
map.reset_password '/reset_password', :controller => 'users', :action => 'reset_password'
1
2
3
4
5
6
7
8
9
10
11
12
# app/models/user_observer.rb
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?
    UserNotifier.deliver_forgot_password(user) if user.recently_forgot_password?
    UserNotifier.deliver_reset_password(user) if user.recently_reset_password?   
  end
end

Update

But of course, there's a much better resource for the plugins, I was just referred to it after this long post from the man himself => Rick's Stikipad for Acts As Authenticated and RESTful authentication.

The additional methods for activation/forgot_password/reset_password does not fall under REST.

[ Last updated: June 04, 2008 @ 04:35 PM ]


4 Responses to...
“Restful_authentication & Activation”

  1. nicolash:

    according to the api http://api.rubyonrails.com/classes/ActionMailer/Base.html (and Ryan in http://railscasts.com/episodes/61) you are not supposed to use instance-variables for subject and so on but plain variables

    @recipients = "#{user.email}"

    ...

    change to:

    recipients = "#{user.email}"

    ...



    Posted:
  2. nicolash:

    sorry - to fast to tired

    change from: @recipients = "#{user.email}" to recipients "#{user.email}"

    (no @ and no =)



    Posted:
  3. carmelyne:

    Thanks Nicolash, I will look into it. Beast still uses instance variables too http://svn.techno-weenie.net/projects/beast/tags/rel-1.0/app/models/user_mailer.rb

    What's the exact reason why we can't use instance variables?



    Posted:
  4. nicolash:

    it is not that you can't use instance variables but setting the variables via the configuration methods seems to be "the prefered way to do it". And Beast - they just use the plug without checking it. I do the same usually ;-).

    The "Why": This should be answered by someone more advanced then me, but it remembers me foe example of going from @params to params. Seems to be a tendency to abstract away the setting of variables via methods - maybe to allow rails to change things in the future without breaking stuff, 'cause if you go via methods rails has a hook to tweak your settings - but as i said this is just an educated(?) guess and I would appreciate if some one else answers the "Why".



    Posted:

Sorry, comments are closed for this article.

Snippets of 06/24/07

Rails 'A'..'Z' Paginate

1
2
3
4
5
6
7
8
9
10
11
# Starts with 'A'..'Z' Paginate / model
def self.sort(sort)
  if sort
    find(:all, :conditions => ['name LIKE ?', "#{sort}%"])
  else
    find(:all, :order => 'name')
  end  
end

# index action / controller
@models = Model.sort(params[:sort]) 

Recent Posts...

RailsConf 2006
I heart devChix