Как стать автором
Обновить

Как мы Email рассылки делали

Время на прочтение2 мин
Количество просмотров3.1K
Привет, Хабр!

Давно уже собирался написать о то как мы в своих реализовывали email-рассылки, да все никак руки не доходили. В общем не мне вам рассказывать о пользе email-маркетинга, просто хочу поделиться техническими деталями реализации этой задачи на Ruby on Rails.

Задача


Нужно, чтобы пользователи периодически по определенному условию получали email-ы. Например: Пользователь зарегистрировался 5 дней назад.

Реализация


Каждое отправленное email-сообщение необходимо логировать, чтобы знать отправляли ли мы уже такому-то пользователю такое-то письмо или нет. Для начала создаем модель EmailLog

rails g model EmailLog user:belongs_to type:string

Далее описываем класс уведомления, который производит отправку сообщений и записывает лог:

app/services/notifications/base.rb

module Notifications
  module Notification
    class Base
      attr_reader :user

      def initialize(user)
        @user = user
      end

      def perform?
        false
      end

      def send!
        NotificationMailer.send(notification_type, user).deliver
        create_log!
      end

      private
      def notification_params
        {
          user_id: user.id,
          type: notification_type
        }
      end

      def notification_type
        self.class.name.demodulize.underscore
      end

      def create_log!
        EmailLog.create!(notification_params)
      end
    end
  end
end

Теперь мы хотим отправить через 5 дней после регистрации письмо с содержанием наподобие: «Эй, вы зарегистрировались, но так ничего и не купили!». Нам нужно описать класс этого уведомления

app/services/notifications/notification/five_days_after_registration.rb

module Notifications
  module Notification
    class FiveDaysAfterRegistration < Base

      def perform?
        user.created_at.to_date == 5.days.ago.to_date && EmailLog.where(log_params).blank?
      end
    end
  end
end

И тут самое интересное, все это необходимо периодически запускать. Нужен класс, который пробегал бы по всем типам уведомлений и отправлял бы их в зависимости от их условий. Создадим класс Worker

app/services/notifications/worker.rb

module Notifications
  class Worker
    EMAIL_TYPES = %w(
        five_days_after_registration
      )

    attr_reader :user

    def initialize(user)
      @user = user
    end

    def go!
      EMAIL_TYPES.each do |notification_type|
        notification_class = "notifications/notification/#{notification_type}".classify.constantize

        notification = notification_class.new(user)
        if notification.perform?
          notification.send!

          puts "Notification «#{notification_type}» was sent to #{user.email}"
          break
        end
      end
    end
  end
end

Готово. Итак, чтобы отправить уведомления пользователю можно просто написать в консоли:

Notifications::Worker.new(user).go!

И все уведомления, условиям которых удовлетворит текущий юзер отправятся.

Но нам нужно делать рассылку по всей базе пользователей. Для этого отлично подходит rake task, который мы будем запускать каждый день, например, в 10 утра по cron-у. Для этого нам нужен gem whenever.

lib/tasks/notifications.rake

namespace :notifications do
  desc 'Lets send emails'
  task send: :environment do
    User.where(receive_email_notifications: true).each do |user|
      Notifications::Worker.new(user).go!
    end
  end
end


config/schedule.rb

every :day, at: '10:00am' do
  rake 'notifications:send', output: 'log/notifications.log'
end


Ну вот и все, рассылка работает! Если у вас есть вопросы пишите комментарии, если нет вопросов, то тоже пишите комментарии ;)
Теги:
Хабы:
0
Комментарии0

Публикации

Изменить настройки темы

Истории

Работа

Программист Ruby
9 вакансий
Ruby on Rails
12 вакансий

Ближайшие события

PG Bootcamp 2024
Дата16 апреля
Время09:30 – 21:00
Место
МинскОнлайн
EvaConf 2024
Дата16 апреля
Время11:00 – 16:00
Место
МоскваОнлайн
Weekend Offer в AliExpress
Дата20 – 21 апреля
Время10:00 – 20:00
Место
Онлайн