Skip to content

Latest commit

 

History

History
96 lines (78 loc) · 3.86 KB

mailers.md

File metadata and controls

96 lines (78 loc) · 3.86 KB

ActionMailer

Mailers are another component of Rails, just like models or controllers. Mailers are similar to controller in that the mailer actions correspond to views (the body of the email), but they differ in that you will explicitly call the mailer method (opposed to routes doing it for you). Let's take a quick look at setting up a basic mailer.

rails generate mailer ClubMailer

The mailer generator creates a mailer file (app/mailers/club_mailer.rb) and a dir for the corresponding views to go into (app/views/club_mailer). The mailer file is a class that inherits from ActionMailer::Base, this class gives us the mail specific methods such as mail. Lets start by creating a method in club_mailer.rb to send out a congratulatory email inviting the user to come to the club (yes this tutorial changed from golf clubs to dance clubs).

class ClubMailer < ActionMailer::Base
  default from: "[email protected]"

  def join_us
    @club = Club.first
    mail(to: "[email protected]", subject: "Come join #{@club.name}" for a dance party!)
  end
end

For now, this email always sends to me. But, let's start trying to use this mailer through the rails console.

rails console
club_mailer = ClubMailer.join_us
# => ActionView::MissingTemplate: Missing template club_mailer/join_us

We get an error asking for a template, so let's create one

touch app/views/club_mailer/join_us.html.erb
rails console
club_mailer = ClubMailer.join_us
# => #<Mail::Message:70293938654000, ...

Great, so now it returns this Mail::Message object, this object has a method called .deliver, which will actually try to connect to a mail server and send the email.

club_mailer.deliver
#...
# => Sent mail to [email protected]
#...

It looks like this email was successfully sent, but you'll never actually get it because it's not actually hooked up to a mail server. Let's hook one up. You can use pretty much any email server including your personal gmail account. For a production application you would want to use something better suited for large scale sending. Look into Mandrill by Mailchimp, which is a transactional email service meant for production.

We'll use Gmail credentials to add some configuration to our development.rb, inside of the configure block:

config.action_mailer.raise_delivery_errors = true
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
  address:              'smtp.gmail.com',
  port:                 587,
  domain:               'example.com',
  user_name:            ENV["MAIL_USERNAME"], # your gmail login
  password:             ENV["MAIL_PASSWORD"], # your gmail password
  authentication:       'plain',
  enable_starttls_auto: true  
}

Now if we try the same mailer, we should receive an email:

    club_mailer = ClubMailer.join_us
    club_mailer.deliver

Right now the club we're sending an email about is hardcoded in (Club.first), we can make a mailer method take any number of arguments, just like any other ruby method. We'll make the .join_us method take a club id, and in the method we'll use the id to look the club up from the database.

class ClubMailer < ActionMailer::Base
  default from: "[email protected]"

  def join_us(club_id)
    @club = Club.find(club_id)
    mail(to: "[email protected]", subject: "Come join #{@club.name} for a dance party!")
  end

end

Next, let's integrate this idea with our application, for now we'll just have it sent the email when someone chooses a club, which happens in our PlayerClubsController create action:

class PlayerClubsController < ApplicationController
  def create
    @club = Club.find(params[:club_id])
    PlayerClub.create(club_id: @club.id, player_id: current_user.id)
    ClubMailer.join_us(@club.id).deliver
    redirect_to root_path
  end
end