Привет, Хабр!
Давно уже собирался написать о то как мы в своих реализовывали 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
Ну вот и все, рассылка работает! Если у вас есть вопросы пишите комментарии, если нет вопросов, то тоже пишите комментарии ;)