Your SlideShare is downloading. ×
0
Sending Email
With Callbacks
A look at ActionMailer and
the ActiveRecord life cycle
ActionMailer
The email library that comes with Rails
Mailers
Mailers
 Mailers can be used to send email from Rails
Mailers
 Mailers can be used to send email from Rails
   Supports plain text, HTML, and multi-part emails
Mailers
 Mailers can be used to send email from Rails
   Supports plain text, HTML, and multi-part emails
   Supports atta...
Mailers
 Mailers can be used to send email from Rails
   Supports plain text, HTML, and multi-part emails
   Supports atta...
Mailers
 Mailers can be used to send email from Rails
   Supports plain text, HTML, and multi-part emails
   Supports atta...
Mailers
 Mailers can be used to send email from Rails
   Supports plain text, HTML, and multi-part emails
   Supports atta...
M and V, Without the C
M and V, Without the C

Mailer structure is a bit different than other parts of Rails
M and V, Without the C

Mailer structure is a bit different than other parts of Rails
  It’s a model
M and V, Without the C

Mailer structure is a bit different than other parts of Rails
  It’s a model
  But it has views
M and V, Without the C

Mailer structure is a bit different than other parts of Rails
  It’s a model
  But it has views
Yo...
Email Example
Email Example

Let’s say I have an application built that requires users
to login to see any content
Email Example

Let’s say I have an application built that requires users
to login to see any content
I have created a User...
Email Example

Let’s say I have an application built that requires users
to login to see any content
I have created a User...
Email Example

Let’s say I have an application built that requires users
to login to see any content
I have created a User...
A Problem
A Problem


I really need to make sure users give me a valid email
A Problem


I really need to make sure users give me a valid email
Authlogic checks the email address format, but you
can ...
Adding Authentication
Adding Authentication

When a user signs up:
Adding Authentication

When a user signs up:
  We will send them an email with a special link in it
Adding Authentication

When a user signs up:
  We will send them an email with a special link in it
  Clicking that link w...
Adding Authentication

When a user signs up:
  We will send them an email with a special link in it
  Clicking that link w...
Adding Authentication

When a user signs up:
  We will send them an email with a special link in it
  Clicking that link w...
Generate a Mailer
Generate a Mailer
We call script/
generate as usual
                    $ ruby script/generate mailer user_notifier activat...
Generate a Mailer
We call script/
generate as usual
We ask for a mailer   $ ruby script/generate mailer user_notifier activ...
Generate a Mailer
We call script/
generate as usual
We ask for a mailer       $ ruby script/generate mailer user_notifier a...
app/models/user_notifier.rb
The generated mailer gets us started
class UserNotifier < ActionMailer::Base
         def activation(sent_at = Time.now)
           subject 'UserNotifier#activat...
class UserNotifier < ActionMailer::Base
         def activation(sent_at = Time.now)
           subject 'UserNotifier#activat...
class UserNotifier < ActionMailer::Base
         def activation(sent_at = Time.now)
           subject 'UserNotifier#activat...
class UserNotifier < ActionMailer::Base
         def activation(sent_at = Time.now)
           subject 'UserNotifier#activat...
class UserNotifier < ActionMailer::Base
         def activation(sent_at = Time.now)
           subject 'UserNotifier#activat...
Customized to our Needs
We will work with a User since that makes sense
for what we are trying to do
class UserNotifier < ActionMailer::Base
         def activation(user)
           subject 'Activate Your Account'
          ...
class UserNotifier < ActionMailer::Base
         def activation(user)
           subject 'Activate Your Account'
          ...
class UserNotifier < ActionMailer::Base
         def activation(user)
           subject 'Activate Your Account'
          ...
class UserNotifier < ActionMailer::Base
         def activation(user)
           subject 'Activate Your Account'
          ...
The Email Content
This is the code from
app/views/user_notifier/activation.erb
Welcome to the Secure Application.

Please click the following link to activate your account:

 <%= activate_url(:token =>...
Welcome to the Secure Application.

Please click the following link to activate your account:

 <%= activate_url(:token =>...
Welcome to the Secure Application.

Please click the following link to activate your account:

 <%= activate_url(:token =>...
Welcome to the Secure Application.

Please click the following link to activate your account:

 <%= activate_url(:token =>...
Sending an Email
Sending an Email

You can send an email
from anywhere in the
application
Sending an Email

You can send an email
from anywhere in the
application
                        UserNotifier.deliver_activ...
Mailers in Production
Mailers in Production

 By default, ActionMailer will try to use sendmail to
 deliver emails in production
Mailers in Production

 By default, ActionMailer will try to use sendmail to
 deliver emails in production
   This works o...
Mailers in Production

 By default, ActionMailer will try to use sendmail to
 deliver emails in production
   This works o...
Mailers in Production

 By default, ActionMailer will try to use sendmail to
 deliver emails in production
   This works o...
Callbacks
Taking actions during the ActiveRecord life cycle
The ActiveRecord Life Cycle
The ActiveRecord Life Cycle
Models have a life cycle
The ActiveRecord Life Cycle
Models have a life cycle
  They are created
The ActiveRecord Life Cycle
Models have a life cycle
  They are created
  Read from the database
The ActiveRecord Life Cycle
Models have a life cycle
  They are created
  Read from the database
  Updated
The ActiveRecord Life Cycle
Models have a life cycle
  They are created
  Read from the database
  Updated
  Destroyed
The ActiveRecord Life Cycle
Models have a life cycle
  They are created
  Read from the database
  Updated
  Destroyed
Cal...
The Callback Hooks
The Callback Hooks
after_initialize*
The Callback Hooks
after_initialize*
before_save
The Callback Hooks
after_initialize*
before_save
before_create/update
The Callback Hooks
after_initialize*
before_save
before_create/update
before_validation
The Callback Hooks
after_initialize*
before_save
before_create/update
before_validation
before_validation_on_
create/update
The Callback Hooks
after_initialize*
before_save
before_create/update
before_validation
before_validation_on_
create/updat...
The Callback Hooks
after_initialize*       after_validation_on_cr
                        eate/update
before_save
before_c...
The Callback Hooks
after_initialize*       after_validation_on_cr
                        eate/update
before_save
        ...
The Callback Hooks
after_initialize*       after_validation_on_cr
                        eate/update
before_save
        ...
The Callback Hooks
after_initialize*       after_validation_on_cr
                        eate/update
before_save
        ...
The Callback Hooks
after_initialize*       after_validation_on_cr
                        eate/update
before_save
        ...
The Callback Hooks
after_initialize*       after_validation_on_cr
                        eate/update
before_save
        ...
Building a Callback
Just choose the type of callback, name a
method, and write a matching Ruby method
class User < ActiveRecord::Base
        acts_as_authentic

        after_create :send_activation_email

        def send_a...
class User < ActiveRecord::Base
        acts_as_authentic

        after_create :send_activation_email

        def send_a...
class User < ActiveRecord::Base
        acts_as_authentic

        after_create :send_activation_email

        def send_a...
class User < ActiveRecord::Base
        acts_as_authentic

        after_create :send_activation_email

        def send_a...
Not Just for Email
Not Just for Email
 Sending email using callbacks is a common usage
Not Just for Email
 Sending email using callbacks is a common usage
 However, callbacks are a general tool with many uses
Not Just for Email
 Sending email using callbacks is a common usage
 However, callbacks are a general tool with many uses
...
Not Just for Email
 Sending email using callbacks is a common usage
 However, callbacks are a general tool with many uses
...
Not Just for Email
 Sending email using callbacks is a common usage
 However, callbacks are a general tool with many uses
...
Completing the Example
We need to make some minor changes and
add a controller to get activation working
Migrating in Activation Fields
Rails migrations are pretty smart and can guess
where you want to add the fields
$ ruby script/generate migration add_activation_fields_to_users
                        perishable_token:string
           ...
$ ruby script/generate migration add_activation_fields_to_users
                        perishable_token:string
           ...
$ ruby script/generate migration add_activation_fields_to_users
                        perishable_token:string
           ...
$ ruby script/generate migration add_activation_fields_to_users
                          perishable_token:string
         ...
$ ruby script/generate migration add_activation_fields_to_users
                          perishable_token:string
         ...
$ ruby script/generate migration add_activation_fields_to_users
                          perishable_token:string
         ...
Adding Activations
We look the user up by token, activate them,
and log them in
$ ruby script/generate controller activations




Adding Activations
We look the user up by token, activate them,
and log ...
$ ruby script/generate controller activations


   class ActivationsController < ApplicationController
    def create
    ...
$ ruby script/generate controller activations


   class ActivationsController < ApplicationController
    def create
    ...
$ ruby script/generate controller activations


   class ActivationsController < ApplicationController
    def create
    ...
$ ruby script/generate controller activations


   class ActivationsController < ApplicationController
    def create
    ...
Email Routing
We can’t make an email link POST,
so I created a custom route for the action
ActionController::Routing::Routes.draw do |map|
 map.resources :users
 map.resource :user_session

 map.login "login", :co...
ActionController::Routing::Routes.draw do |map|
 map.resources :users
 map.resource :user_session

 map.login "login", :co...
The Old Sign-up
Our old controller logs them in as they are
created and we can’t have that
class UsersController < ApplicationController
      def new
        @user = User.new
      end

      def create
       @u...
class UsersController < ApplicationController
      def new
        @user = User.new
      end

      def create
       @u...
class UsersController < ApplicationController
      def new
        @user = User.new
      end

      def create
       @u...
Creation Without Login
Now we don’t log them in and we tell them to
check their email
class UsersController < ApplicationController
 def new
   @user = User.new
 end

 def create
  @user = User.new(params[:us...
class UsersController < ApplicationController
 def new
   @user = User.new
 end

 def create
  @user = User.new(params[:us...
class UsersController < ApplicationController
 def new
   @user = User.new
 end

 def create
  @user = User.new(params[:us...
Activations in Action
Let’s see what we have created
Signing Up
I can create a new user with
my email address and desired password
Signing Up
I can create a new user with
my email address and desired password
Time to Check Email
I wasn’t logged in, as planned
Time to Check Email
I wasn’t logged in, as planned
Can’t Login Yet
I can’t login yet either,
since my account isn’t active yet
Can’t Login Yet
I can’t login yet either,
since my account isn’t active yet
log/development.rb
In development mode, emails are printed to
the log file (clear logs with: rake log:clear)
Sent mail to james@graysoftinc.com

   Date: Sun, 7 Mar 2010 15:10:11 -0600
   From: admin@secureapp.com
   To: james@gray...
Activated and Logged In
Visiting the URL completes the process
Activated and Logged In
Visiting the URL completes the process
Questions?
User Emails Lab
Your book has instructions for how to add
email notifications to your application
Upcoming SlideShare
Loading in...5
×

Sending Email with Rails

7,857

Published on

This was the eight speech of a three day Rails training I gave in Tulsa, OK in the spring 2010.

Published in: Technology

Transcript of "Sending Email with Rails"

  1. 1. Sending Email With Callbacks A look at ActionMailer and the ActiveRecord life cycle
  2. 2. ActionMailer The email library that comes with Rails
  3. 3. Mailers
  4. 4. Mailers Mailers can be used to send email from Rails
  5. 5. Mailers Mailers can be used to send email from Rails Supports plain text, HTML, and multi-part emails
  6. 6. Mailers Mailers can be used to send email from Rails Supports plain text, HTML, and multi-part emails Supports attachments
  7. 7. Mailers Mailers can be used to send email from Rails Supports plain text, HTML, and multi-part emails Supports attachments Multiple send modes including: sendmail and SMTP
  8. 8. Mailers Mailers can be used to send email from Rails Supports plain text, HTML, and multi-part emails Supports attachments Multiple send modes including: sendmail and SMTP Mailers can also be used to receive emails
  9. 9. Mailers Mailers can be used to send email from Rails Supports plain text, HTML, and multi-part emails Supports attachments Multiple send modes including: sendmail and SMTP Mailers can also be used to receive emails Parses the email data into a Ruby object
  10. 10. M and V, Without the C
  11. 11. M and V, Without the C Mailer structure is a bit different than other parts of Rails
  12. 12. M and V, Without the C Mailer structure is a bit different than other parts of Rails It’s a model
  13. 13. M and V, Without the C Mailer structure is a bit different than other parts of Rails It’s a model But it has views
  14. 14. M and V, Without the C Mailer structure is a bit different than other parts of Rails It’s a model But it has views You can think of it as rendering content for the user, just not through a browser
  15. 15. Email Example
  16. 16. Email Example Let’s say I have an application built that requires users to login to see any content
  17. 17. Email Example Let’s say I have an application built that requires users to login to see any content I have created a User model and built the controller that allows them to sign-up
  18. 18. Email Example Let’s say I have an application built that requires users to login to see any content I have created a User model and built the controller that allows them to sign-up I have also wired up a login system using Authlogic
  19. 19. Email Example Let’s say I have an application built that requires users to login to see any content I have created a User model and built the controller that allows them to sign-up I have also wired up a login system using Authlogic The whole thing works now
  20. 20. A Problem
  21. 21. A Problem I really need to make sure users give me a valid email
  22. 22. A Problem I really need to make sure users give me a valid email Authlogic checks the email address format, but you can only know an email is valid by sending a message
  23. 23. Adding Authentication
  24. 24. Adding Authentication When a user signs up:
  25. 25. Adding Authentication When a user signs up: We will send them an email with a special link in it
  26. 26. Adding Authentication When a user signs up: We will send them an email with a special link in it Clicking that link will authenticate their address
  27. 27. Adding Authentication When a user signs up: We will send them an email with a special link in it Clicking that link will authenticate their address We won’t allow non-authenticated users access to the site
  28. 28. Adding Authentication When a user signs up: We will send them an email with a special link in it Clicking that link will authenticate their address We won’t allow non-authenticated users access to the site After authentication, their account will work normally
  29. 29. Generate a Mailer
  30. 30. Generate a Mailer We call script/ generate as usual $ ruby script/generate mailer user_notifier activation exists app/models/ create app/views/user_notifier exists test/unit/ create test/fixtures/user_notifier create app/models/user_notifier.rb create test/unit/user_notifier_test.rb create app/views/user_notifier/activation.erb create test/fixtures/user_notifier/activation
  31. 31. Generate a Mailer We call script/ generate as usual We ask for a mailer $ ruby script/generate mailer user_notifier activation exists app/models/ and name it create app/views/user_notifier exists test/unit/ create test/fixtures/user_notifier user_notifier create app/models/user_notifier.rb create test/unit/user_notifier_test.rb create app/views/user_notifier/activation.erb create test/fixtures/user_notifier/activation
  32. 32. Generate a Mailer We call script/ generate as usual We ask for a mailer $ ruby script/generate mailer user_notifier activation exists app/models/ and name it create app/views/user_notifier exists test/unit/ create test/fixtures/user_notifier user_notifier create app/models/user_notifier.rb create test/unit/user_notifier_test.rb create app/views/user_notifier/activation.erb create test/fixtures/user_notifier/activation Optionally, we can also pass the names of emails to create
  33. 33. app/models/user_notifier.rb The generated mailer gets us started
  34. 34. class UserNotifier < ActionMailer::Base def activation(sent_at = Time.now) subject 'UserNotifier#activation' recipients '' from '' sent_on sent_at body :greeting => 'Hi,' end end app/models/user_notifier.rb The generated mailer gets us started
  35. 35. class UserNotifier < ActionMailer::Base def activation(sent_at = Time.now) subject 'UserNotifier#activation' recipients '' from '' sent_on sent_at body :greeting => 'Hi,' end end app/models/user_notifier.rb The generated mailer gets us started
  36. 36. class UserNotifier < ActionMailer::Base def activation(sent_at = Time.now) subject 'UserNotifier#activation' recipients '' from '' sent_on sent_at body :greeting => 'Hi,' end end app/models/user_notifier.rb The generated mailer gets us started
  37. 37. class UserNotifier < ActionMailer::Base def activation(sent_at = Time.now) subject 'UserNotifier#activation' recipients '' from '' sent_on sent_at body :greeting => 'Hi,' end end app/models/user_notifier.rb The generated mailer gets us started
  38. 38. class UserNotifier < ActionMailer::Base def activation(sent_at = Time.now) subject 'UserNotifier#activation' recipients '' from '' sent_on sent_at body :greeting => 'Hi,' end end app/models/user_notifier.rb The generated mailer gets us started
  39. 39. Customized to our Needs We will work with a User since that makes sense for what we are trying to do
  40. 40. class UserNotifier < ActionMailer::Base def activation(user) subject 'Activate Your Account' recipients user.email from 'admin@secureapp.com' sent_on Time.now body :user => user end end Customized to our Needs We will work with a User since that makes sense for what we are trying to do
  41. 41. class UserNotifier < ActionMailer::Base def activation(user) subject 'Activate Your Account' recipients user.email from 'admin@secureapp.com' sent_on Time.now body :user => user end end Customized to our Needs We will work with a User since that makes sense for what we are trying to do
  42. 42. class UserNotifier < ActionMailer::Base def activation(user) subject 'Activate Your Account' recipients user.email from 'admin@secureapp.com' sent_on Time.now body :user => user end end Customized to our Needs We will work with a User since that makes sense for what we are trying to do
  43. 43. class UserNotifier < ActionMailer::Base def activation(user) subject 'Activate Your Account' recipients user.email from 'admin@secureapp.com' sent_on Time.now body :user => user end end Customized to our Needs We will work with a User since that makes sense for what we are trying to do
  44. 44. The Email Content This is the code from app/views/user_notifier/activation.erb
  45. 45. Welcome to the Secure Application. Please click the following link to activate your account: <%= activate_url(:token => @user.perishable_token, :host => "localhost:3000") %> The Email Content This is the code from app/views/user_notifier/activation.erb
  46. 46. Welcome to the Secure Application. Please click the following link to activate your account: <%= activate_url(:token => @user.perishable_token, :host => "localhost:3000") %> The Email Content This is the code from app/views/user_notifier/activation.erb
  47. 47. Welcome to the Secure Application. Please click the following link to activate your account: <%= activate_url(:token => @user.perishable_token, :host => "localhost:3000") %> The Email Content This is the code from app/views/user_notifier/activation.erb
  48. 48. Welcome to the Secure Application. Please click the following link to activate your account: <%= activate_url(:token => @user.perishable_token, :host => "localhost:3000") %> The Email Content This is the code from app/views/user_notifier/activation.erb
  49. 49. Sending an Email
  50. 50. Sending an Email You can send an email from anywhere in the application
  51. 51. Sending an Email You can send an email from anywhere in the application UserNotifier.deliver_activation(user) Just call deliver_EMAIL() where EMAIL is the name of the message
  52. 52. Mailers in Production
  53. 53. Mailers in Production By default, ActionMailer will try to use sendmail to deliver emails in production
  54. 54. Mailers in Production By default, ActionMailer will try to use sendmail to deliver emails in production This works on a lot of servers but is not robust
  55. 55. Mailers in Production By default, ActionMailer will try to use sendmail to deliver emails in production This works on a lot of servers but is not robust I recommend setting up a Gmail account and configuring ActionMailer to send via SMTP
  56. 56. Mailers in Production By default, ActionMailer will try to use sendmail to deliver emails in production This works on a lot of servers but is not robust I recommend setting up a Gmail account and configuring ActionMailer to send via SMTP You may also wish to shut off ActionMailer’s default error raising behavior
  57. 57. Callbacks Taking actions during the ActiveRecord life cycle
  58. 58. The ActiveRecord Life Cycle
  59. 59. The ActiveRecord Life Cycle Models have a life cycle
  60. 60. The ActiveRecord Life Cycle Models have a life cycle They are created
  61. 61. The ActiveRecord Life Cycle Models have a life cycle They are created Read from the database
  62. 62. The ActiveRecord Life Cycle Models have a life cycle They are created Read from the database Updated
  63. 63. The ActiveRecord Life Cycle Models have a life cycle They are created Read from the database Updated Destroyed
  64. 64. The ActiveRecord Life Cycle Models have a life cycle They are created Read from the database Updated Destroyed Callbacks allow us to run code at points in this cycle
  65. 65. The Callback Hooks
  66. 66. The Callback Hooks after_initialize*
  67. 67. The Callback Hooks after_initialize* before_save
  68. 68. The Callback Hooks after_initialize* before_save before_create/update
  69. 69. The Callback Hooks after_initialize* before_save before_create/update before_validation
  70. 70. The Callback Hooks after_initialize* before_save before_create/update before_validation before_validation_on_ create/update
  71. 71. The Callback Hooks after_initialize* before_save before_create/update before_validation before_validation_on_ create/update after_validation
  72. 72. The Callback Hooks after_initialize* after_validation_on_cr eate/update before_save before_create/update before_validation before_validation_on_ create/update after_validation
  73. 73. The Callback Hooks after_initialize* after_validation_on_cr eate/update before_save after_save before_create/update before_validation before_validation_on_ create/update after_validation
  74. 74. The Callback Hooks after_initialize* after_validation_on_cr eate/update before_save after_save before_create/update after_create/update before_validation before_validation_on_ create/update after_validation
  75. 75. The Callback Hooks after_initialize* after_validation_on_cr eate/update before_save after_save before_create/update after_create/update before_validation after_find* before_validation_on_ create/update after_validation
  76. 76. The Callback Hooks after_initialize* after_validation_on_cr eate/update before_save after_save before_create/update after_create/update before_validation after_find* before_validation_on_ create/update before_destroy after_validation
  77. 77. The Callback Hooks after_initialize* after_validation_on_cr eate/update before_save after_save before_create/update after_create/update before_validation after_find* before_validation_on_ create/update before_destroy after_validation after_destroy
  78. 78. Building a Callback Just choose the type of callback, name a method, and write a matching Ruby method
  79. 79. class User < ActiveRecord::Base acts_as_authentic after_create :send_activation_email def send_activation_email reset_perishable_token! UserNotifier.deliver_activation(self) end end Building a Callback Just choose the type of callback, name a method, and write a matching Ruby method
  80. 80. class User < ActiveRecord::Base acts_as_authentic after_create :send_activation_email def send_activation_email reset_perishable_token! UserNotifier.deliver_activation(self) end end Building a Callback Just choose the type of callback, name a method, and write a matching Ruby method
  81. 81. class User < ActiveRecord::Base acts_as_authentic after_create :send_activation_email def send_activation_email reset_perishable_token! UserNotifier.deliver_activation(self) end end Building a Callback Just choose the type of callback, name a method, and write a matching Ruby method
  82. 82. class User < ActiveRecord::Base acts_as_authentic after_create :send_activation_email def send_activation_email reset_perishable_token! UserNotifier.deliver_activation(self) end end Building a Callback Just choose the type of callback, name a method, and write a matching Ruby method
  83. 83. Not Just for Email
  84. 84. Not Just for Email Sending email using callbacks is a common usage
  85. 85. Not Just for Email Sending email using callbacks is a common usage However, callbacks are a general tool with many uses
  86. 86. Not Just for Email Sending email using callbacks is a common usage However, callbacks are a general tool with many uses For example:
  87. 87. Not Just for Email Sending email using callbacks is a common usage However, callbacks are a general tool with many uses For example: You might update an average_review_rating column with an after_save on Review
  88. 88. Not Just for Email Sending email using callbacks is a common usage However, callbacks are a general tool with many uses For example: You might update an average_review_rating column with an after_save on Review You might generate a login column from a provided email address in a before_validation on User
  89. 89. Completing the Example We need to make some minor changes and add a controller to get activation working
  90. 90. Migrating in Activation Fields Rails migrations are pretty smart and can guess where you want to add the fields
  91. 91. $ ruby script/generate migration add_activation_fields_to_users perishable_token:string active:boolean Migrating in Activation Fields Rails migrations are pretty smart and can guess where you want to add the fields
  92. 92. $ ruby script/generate migration add_activation_fields_to_users perishable_token:string active:boolean Migrating in Activation Fields Rails migrations are pretty smart and can guess where you want to add the fields
  93. 93. $ ruby script/generate migration add_activation_fields_to_users perishable_token:string active:boolean Migrating in Activation Fields Rails migrations are pretty smart and can guess where you want to add the fields
  94. 94. $ ruby script/generate migration add_activation_fields_to_users perishable_token:string active:boolean class AddActivationFieldsToUsers < ActiveRecord::Migration def self.up add_column :users, :perishable_token, :string add_column :users, :active, :boolean, :default => false, :null => false end def self.down remove_column :users, :active remove_column :users, :perishable_token end end Migrating in Activation Fields Rails migrations are pretty smart and can guess where you want to add the fields
  95. 95. $ ruby script/generate migration add_activation_fields_to_users perishable_token:string active:boolean class AddActivationFieldsToUsers < ActiveRecord::Migration def self.up add_column :users, :perishable_token, :string add_column :users, :active, :boolean, :default => false, :null => false end def self.down remove_column :users, :active remove_column :users, :perishable_token end end Migrating in Activation Fields Rails migrations are pretty smart and can guess where you want to add the fields
  96. 96. $ ruby script/generate migration add_activation_fields_to_users perishable_token:string active:boolean class AddActivationFieldsToUsers < ActiveRecord::Migration def self.up add_column :users, :perishable_token, :string add_column :users, :active, :boolean, :default => false, :null => false end def self.down remove_column :users, :active remove_column :users, :perishable_token end end $ rake db:migrate Migrating in Activation Fields Rails migrations are pretty smart and can guess where you want to add the fields
  97. 97. Adding Activations We look the user up by token, activate them, and log them in
  98. 98. $ ruby script/generate controller activations Adding Activations We look the user up by token, activate them, and log them in
  99. 99. $ ruby script/generate controller activations class ActivationsController < ApplicationController def create if @user = User.find_using_perishable_token(params[:token]) @user.active = true # activate the user @user.save UserSession.create(@user) # log them in flash[:notice] = "User activated." else flash[:error] = "User not found." end redirect_to root_path end end Adding Activations We look the user up by token, activate them, and log them in
  100. 100. $ ruby script/generate controller activations class ActivationsController < ApplicationController def create if @user = User.find_using_perishable_token(params[:token]) @user.active = true # activate the user @user.save UserSession.create(@user) # log them in flash[:notice] = "User activated." else flash[:error] = "User not found." end redirect_to root_path end end Adding Activations We look the user up by token, activate them, and log them in
  101. 101. $ ruby script/generate controller activations class ActivationsController < ApplicationController def create if @user = User.find_using_perishable_token(params[:token]) @user.active = true # activate the user @user.save UserSession.create(@user) # log them in flash[:notice] = "User activated." else flash[:error] = "User not found." end redirect_to root_path end end Adding Activations We look the user up by token, activate them, and log them in
  102. 102. $ ruby script/generate controller activations class ActivationsController < ApplicationController def create if @user = User.find_using_perishable_token(params[:token]) @user.active = true # activate the user @user.save UserSession.create(@user) # log them in flash[:notice] = "User activated." else flash[:error] = "User not found." end redirect_to root_path end end Adding Activations We look the user up by token, activate them, and log them in
  103. 103. Email Routing We can’t make an email link POST, so I created a custom route for the action
  104. 104. ActionController::Routing::Routes.draw do |map| map.resources :users map.resource :user_session map.login "login", :controller => "user_sessions", :action => "new" map.logout "logout", :controller => "user_sessions", :action => "destroy" map.activate "activate/:token", :controller => "activations", :action => "create" map.root :controller => "home" map.connect ':controller/:action/:id' map.connect ':controller/:action/:id.:format' end Email Routing We can’t make an email link POST, so I created a custom route for the action
  105. 105. ActionController::Routing::Routes.draw do |map| map.resources :users map.resource :user_session map.login "login", :controller => "user_sessions", :action => "new" map.logout "logout", :controller => "user_sessions", :action => "destroy" map.activate "activate/:token", :controller => "activations", :action => "create" map.root :controller => "home" map.connect ':controller/:action/:id' map.connect ':controller/:action/:id.:format' end Email Routing We can’t make an email link POST, so I created a custom route for the action
  106. 106. The Old Sign-up Our old controller logs them in as they are created and we can’t have that
  107. 107. class UsersController < ApplicationController def new @user = User.new end def create @user = User.new(params[:user]) if @user.save flash[:notice] = "Welcome!" redirect_to root_path else flash.now[:error] = "Sign-up could not be completed." render :action => :new end end end The Old Sign-up Our old controller logs them in as they are created and we can’t have that
  108. 108. class UsersController < ApplicationController def new @user = User.new end def create @user = User.new(params[:user]) if @user.save flash[:notice] = "Welcome!" redirect_to root_path else flash.now[:error] = "Sign-up could not be completed." render :action => :new end end end The Old Sign-up Our old controller logs them in as they are created and we can’t have that
  109. 109. class UsersController < ApplicationController def new @user = User.new end def create @user = User.new(params[:user]) if @user.save flash[:notice] = "Welcome!" redirect_to root_path else flash.now[:error] = "Sign-up could not be completed." render :action => :new end end end The Old Sign-up Our old controller logs them in as they are created and we can’t have that
  110. 110. Creation Without Login Now we don’t log them in and we tell them to check their email
  111. 111. class UsersController < ApplicationController def new @user = User.new end def create @user = User.new(params[:user]) if @user.save_without_session_maintenance flash[:notice] = "Please check your email to activate your account." redirect_to login_path else flash.now[:error] = "Sign-up could not be completed." render :action => :new end end end Creation Without Login Now we don’t log them in and we tell them to check their email
  112. 112. class UsersController < ApplicationController def new @user = User.new end def create @user = User.new(params[:user]) if @user.save_without_session_maintenance flash[:notice] = "Please check your email to activate your account." redirect_to login_path else flash.now[:error] = "Sign-up could not be completed." render :action => :new end end end Creation Without Login Now we don’t log them in and we tell them to check their email
  113. 113. class UsersController < ApplicationController def new @user = User.new end def create @user = User.new(params[:user]) if @user.save_without_session_maintenance flash[:notice] = "Please check your email to activate your account." redirect_to login_path else flash.now[:error] = "Sign-up could not be completed." render :action => :new end end end Creation Without Login Now we don’t log them in and we tell them to check their email
  114. 114. Activations in Action Let’s see what we have created
  115. 115. Signing Up I can create a new user with my email address and desired password
  116. 116. Signing Up I can create a new user with my email address and desired password
  117. 117. Time to Check Email I wasn’t logged in, as planned
  118. 118. Time to Check Email I wasn’t logged in, as planned
  119. 119. Can’t Login Yet I can’t login yet either, since my account isn’t active yet
  120. 120. Can’t Login Yet I can’t login yet either, since my account isn’t active yet
  121. 121. log/development.rb In development mode, emails are printed to the log file (clear logs with: rake log:clear)
  122. 122. Sent mail to james@graysoftinc.com Date: Sun, 7 Mar 2010 15:10:11 -0600 From: admin@secureapp.com To: james@graysoftinc.com Subject: Activate Your Account Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8 Welcome to the Secure Application. Please click the following link to activate your account: http://localhost:3000/activate/5HkeFFwiInKfjA4x25q9 log/development.rb In development mode, emails are printed to the log file (clear logs with: rake log:clear)
  123. 123. Activated and Logged In Visiting the URL completes the process
  124. 124. Activated and Logged In Visiting the URL completes the process
  125. 125. Questions?
  126. 126. User Emails Lab Your book has instructions for how to add email notifications to your application
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×