Привет, Хабр!
Давно уже собирался написать о то как мы в своих реализовывали email-рассылки, да все никак руки не доходили. В общем не мне вам рассказывать о пользе email-маркетинга, просто хочу поделиться техническими деталями реализации этой задачи на Ruby on Rails.
Нужно, чтобы пользователи периодически по определенному условию получали email-ы. Например: Пользователь зарегистрировался 5 дней назад.
Каждое отправленное email-сообщение необходимо логировать, чтобы знать отправляли ли мы уже такому-то пользователю такое-то письмо или нет. Для начала создаем модель EmailLog
Далее описываем класс уведомления, который производит отправку сообщений и записывает лог:
Теперь мы хотим отправить через 5 дней после регистрации письмо с содержанием наподобие: «Эй, вы зарегистрировались, но так ничего и не купили!». Нам нужно описать класс этого уведомления
И тут самое интересное, все это необходимо периодически запускать. Нужен класс, который пробегал бы по всем типам уведомлений и отправлял бы их в зависимости от их условий. Создадим класс Worker
Готово. Итак, чтобы отправить уведомления пользователю можно просто написать в консоли:
И все уведомления, условиям которых удовлетворит текущий юзер отправятся.
Но нам нужно делать рассылку по всей базе пользователей. Для этого отлично подходит rake task, который мы будем запускать каждый день, например, в 10 утра по cron-у. Для этого нам нужен gem whenever.
Ну вот и все, рассылка работает! Если у вас есть вопросы пишите комментарии, если нет вопросов, то тоже пишите комментарии ;)
Давно уже собирался написать о то как мы в своих реализовывали 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
Ну вот и все, рассылка работает! Если у вас есть вопросы пишите комментарии, если нет вопросов, то тоже пишите комментарии ;)
