Apane101
Apane101

Reputation: 1123

Email notifications on Rails

So, I have this website that I've built http://leapfm.com/ and more and more users are joining which is fantastic. I've noticed that users sign back on to check if their song has been up-voted. I'd like to automate this process for them.

So, I'd like to implement a feature that sends the user an email when their song is up-voted. I'm not sure if this is possible with my stack specifically.

E.g. for up voting I'm using this gem.

Can I implement somethin' like this? If you need me to provide any additional information, don't be afraid to ask.

song_controller snippit (create action):

def create
    @song = Song.new(song_params)
    @song.user = current_user
    respond_to do |format|
      if @song.save
        format.html { redirect_to @song, notice: 'Song was successfully created.' }
        format.json { render action: 'show', status: :created, location: @song }
      else
        format.html { render action: 'new' }
        format.json { render json: @song.errors, status: :unprocessable_entity }
      end
    end
  end

Upvotes: 3

Views: 4011

Answers (1)

Benjamin Manns
Benjamin Manns

Reputation: 9138

This should be fairly straightforward. What you would want to do is send an email each time a vote record is created. First, within your Vote model, you would set up an after_commit handler when an instance is created.

class Vote
  ...
  after_commit :send_email, :on => :create

  def send_email
    # send the email to whoever owns votable
  end
end

Within the # send the email part, there are several options. The simplest would be to simply configure ActionMailer and deliver emails within that send_email method. There are several methods for setting this up. The one I most recently used was Postmark, for which you would install postmark-rails and add something like the following to your config/environments/production.rb.

config.action_mailer.delivery_method = :postmark
config.action_mailer.postmark_settings = { :api_key => 'your-api-key' }

However, I encourage you to check out the various providers to find one that fits your needs (I can think of Postmark, SendGrid, Mailgun).

Then, run rails generate mailer VoteMailer, which will create a VoteMailer class under app/mailers/vote_mailer.rb. Edit it to fit your needs.

class VoteMailer < ActionMailer::Base
  default from: '[email protected]'

  def vote_notification(voter, song)
    @voter = voter
    @song = song
    @user = @song.user
    mail(to: @user.email, subject: 'Someone voted on your song!')
  end
end

Now, you create a template in app/views/vote_mailer/vote_notification.text.erb.

Hey <%= @user.name %>,

Someone voted on your song, <%= @song.name %>!

Congrats!

Then, use the mailer in your send_email method.

class Vote
  ...
  def send_email
    VoteNotifier.vote_notification(voter, voteable).deliver!
  end
end

This should get you started.

People were commenting earlier about needing to use Delayed Job. This is because sending email can be a slow process. If every time a user clicks 'upvote', they have to wait 5 seconds while the email is sent, they will become dissatisfied with the service.

To avoid this problem, people will take the more time consuming parts of their server request and stick them into a job queue, which will be processed by another server. To achieve this with your emails, you would install delayed_job_active_record and change your send_email method:

class Vote
  ...
  def send_email
    VoteNotifier.delay.vote_notification(voter, voteable)
  end
end

And then in a separate process on your server, run the jobs:work Rake task.

bundle exec rake jobs:work

This process should be running 24/7, just like your web server process.

Upvotes: 8

Related Questions