featured

By Phil WiltNovember 8, 2014

[Student Project] How to add Sucker Punch to your Rails app in 5 easy steps

*In this blog post, Ruby on Rails graduate Phil Wilt explains how to set up Sucker Punch, an asynchronous library for more efficient management of incoming and outgoing emails within a Rails application.*

This app is a boilerplate project for using Action Mailer with Active Job background processing with Rails 4.2. This allows you to send emails using a background process within a single process. If deploying to Heroku, you have no need for a second dyno or complex setup.

Caveats: This is great for simple mailers. If you need something more complex, I recommend using something like Sidekiq. If you’re using this for a contact form, you will have to persist the data in your database until the job has been completed. However, it is possible to just delete the object after the email has been sent (cheap hack).

This is a basic contact list signup example. You could easily extend this to user signup or other applications that need email.

1. Install Rails

First, you’ll need to install Rails 4.2. At the time of writing, the newest Rails version is 4.2.0beta2. Using rvm:

$ rvm use ruby-2.1.3@rails4.2 --create
$ gem install rails --pre

Next, create a new Rails project:

$ mkdir mailer && cd mailer
$ rails new .

2. Install Sucker Punch

Now we’re going to setup Sucker Punch. In Rails 4.2, we can configure Active Jobs to use Sucker Punch as its back-end. This greatly simplifies our lives.

In your Gemfile, add gem 'sucker_punch' and then run bundle install. Next, configure Rails to Sucker Punch the back-end!

# app/config/application.rb

class Application < Rails::Application
  config.active_job.queue_adapter = :sucker_punch

3. Create a Contact

Now we’re going to create a contact. You may use a Rails generator or create the files manually. The end goal is to have the following pieces:

#app/models/contact.rb

class Contact < ActiveRecord::Base
  validates :name, :email, presence: true
end

# app/controller/contacts_controller.rb

class ContactsController < ApplicationController
  def new
    @contact = Contact.new
  end

  def create
    @contact = Contact.new(contact_params)

    if @contact.save
      ContactsMailer.welcome(@contact).deliver_later

      flash[:success] = "You have been added to my contacts!"
      redirect_to root_url
    else
     render :new
    end
  end

  private

  def contact_params
    params.require(:contact).permit(:name, :email)
  end
end

# config/routes.rb
resources :contacts, only: [:new, :create]

From this, you can see we created a model with basic validations, and a controller with the “new” and “create” actions. We then added resources for those actions in our routes.

The real magic happening here in Rails 4.2 is the line:

ContactsMailer.welcome(@contact).deliver_later

This is what allows us to create an Active Job and send it to a Sucker Punch queue. In fact, we don’t even have to set up logging like before, as Active Jobs will log by default. Pretty nice abstraction, ain’t it? Of course, this won’t work without a mailer, so let’s set that up.

4. Setup a Mailer

Now we will setup an Action Mailer to handle our email needs. Again, you can use a generator or do this manually. The end goal is the following pieces:

# app/mailers/contacts_mailer.rb

class ContactsMailer < ActionMailer::Base
  default from: 'me@example.com'

  def welcome(contact)
    @contact = contact

    mail(to: @contact.email, subject: "Welcome to my list #{@contact.name}!")
  end
end

# app/views/contacts_mailer/welcome.html.erb

<%= "Welcome to my contacts list #{@contact.name}" %>

Great! Now we are ready to sign up your friends!

5. Add a Sign Up Form

The last piece of the puzzle! We’ll add a signup form so you can get all your friends’ email addresses.

# app/views/contacts/new.html.erb

<% if @contact.errors.any? %>
  <div class='errors'>
      <ul>
      <% @contact.errors.full_messages.each do |msg| %>
        <li><%= msg %></li>
      <% end %>
    </ul>
  </div>
<% end %>

<%= form_for @contact do |f| %>
  <%= f.label :name, 'Name' %>
  <br />
  <%= f.text_field :name, { placeholder: "Jon Stewart" } %>
  <br />
  <%= f.label :email, 'Email' %>
  <br />
  <%= f.text_field :email, { placeholder: "example@email.com" } %>
  <br />
  <%= f.submit "Sign Up" %>
<% end %>

This form starts by showing any validation errors we may have run into. Then we have our input fields. Simple as that!

You’re ready to add your favorite email provider and start spamming your friends!


Phil Wilt is a Ruby on Rails Development Accelerator graduate. View the full project on his GitHub profile.