我有一个提醒服务,该服务接受一些“更改请求”,然后将它们发送到工作人员队列中,以便日后执行。 每个“更改请求”可以有“前十分钟”提醒,也可以有“后一小时”提醒。将来还会有不同类型的提醒。
我正在寻找最精致的红宝石处理方式,并将每个提醒发送给工作人员很多if语句感觉不对,但我可能是错的!
class ReminderService
# @data
# ten_minute_before: data[:ten_minutes_before_reminder] bool,
# one_hour_after: data[:one_hour_after_reminder] bool,
# user: user,
# price_change_ids: data[:change_requests],
# user_hash: user_hash(user)
attr_accessor :data, :user
def initialize(user, data)
{data[:price_change_ids]}
@user = user
@data = data
end
def run
change_requests
end
def send
reminderWorker.perform_at(action_reminder_at, price_change_id, reminder_type, user, user_hash)
end
def change_requests
data[:price_change_ids]
end
def user_hash
data[:user_hash]
end
def action_reminder_at
DateTime.parse(price_change_at) - 11.minutes
end
def price_change_id
data[:price_change_ids].first.id
end
def price_change_at
data[:user_hash][:price_change_at_time]
end
end
工人服务:
class PriceReminderWorker
include Sidekiq::Worker
sidekiq_options queue: 'price_reminders', retry: true
def perform(price_change_id, reminder, user, data)
id = price_change_id
price_change = priceChangeRequest.find(id)
if reminder[:ten_minutes_before]
reminderMailer.notify(user, data).deliver_later unless price_change.cancelled_at
end
if reminder[:one_hour_after]
Sms::priceChangeSms.new(build_hash(user)).submit unless price_change.cancelled_at
end
end
def build_hash(user)
{
to: Phonelib.parse(user.mobile_number).full_e164,
company_id: user&.company&.id,
user_name: user.first_name,
admin_user_name: data[:from_admin_user],
body: Sms::Message::priceChangeMessage.new(data).build
}
end
end
答案 0 :(得分:1)
如果您真的想要坚持使用当前的PriceChangeRequest
结构,那么我想我会这样做:
class PriceReminderWorker
include Sidekiq::Worker
sidekiq_options queue: 'price_reminders', retry: true
attr_accessor *%w( price_change_id user data ).freeze
def perform(price_change_id, reminder, user, data)
@price_change_id = price_change_id
@user = user
@data = data
%i(
ten_minutes_before
one_hour_after
).each do |time_sym|
send("send_#{time_sym}_reminder") if price_change_request.send("#{time_sym}_reminder")
end if price_change_request
end
private
def user_hash
{
to: Phonelib.parse(user.mobile_number).full_e164,
company_id: user&.company&.id,
user_name: user.first_name,
admin_user_name: data[:from_admin_user],
body: Sms::Message::priceChangeMessage.new(data).build
}
end
def send_ten_minutes_before_reminder
reminderMailer.notify(user, data).deliver_later unless price_change.cancelled_at
end
def send_one_hour_after_reminder
Sms::priceChangeSms.new(user_hash).submit unless price_change.cancelled_at
end
def price_change_request
@price_change_request ||= PriceChangeRequest.find(price_change_id)
end
end
但是,我认为在您的booleans
类上拥有一堆ten_minutes_before_reminder
和one_hour_after_reminder
之类的PriceChangeRequest
并不是一个好主意。尤其是当您开始有很多提醒类型时。您最终可能会得到填充稀疏的布尔值字段,但这并不是很好。而且,每次要添加新的提醒类型时,您都必须运行新的迁移。等等,等等。
如果我是你,我想我很想拥有ReminderTime
类,例如:
# == Schema Information
#
# Table name: reminder_times
#
# id :bigint not null, primary key
# system_name :string not null
# created_at :datetime not null
# updated_at :datetime not null
#
class ReminderTime < ApplicationRecord
validates :system_name, presence: true
has_many :price_change_request_reminder_times
has_many :price_change_requests, through: :price_change_request_reminder_times
end
还有PriceChangeRequestReminderTime
之类的东西
# == Schema Information
#
# Table name: price_change_request_reminder_times
#
# id :bigint not null, primary key
# reminder_time_id :integer not null
# price_change_request_id :integer not null
# created_at :datetime not null
# updated_at :datetime not null
#
class PriceChangeRequestReminderTime < ApplicationRecord
belongs_to :reminder_time
belongs_to :price_change_request
end
然后,在您的PriceChangeRequest
中,执行以下操作:
class PriceChangeRequest < ApplicationRecord
has_many :price_change_request_reminder_times
has_many :reminder_times, through: :price_change_request_reminder_times
def set_reminder_times(*time_syms)
time_syms.each do |time_sym|
reminder_times << ReminderTime.find_or_create_by!(system_name: time_sym)
end
end
def remove_reminder_times(*type_syms)
price_change_request_reminder_times.
where(reminder_time: ReminderTime.find_by(system_name: type_syms)).
destroy_all
end
def reminder_time_names
reminder_times.pluck(:system_name)
end
end
要设置提醒时间,您可以执行以下操作:
@price_change_request.set_reminder_times :ten_minutes_before
或
@price_change_request.set_reminder_times :ten_minutes_before, :one_hour_after
要删除提醒时间,您可以执行以下操作:
@price_change_request.remove_reminder_times :ten_minutes_before
或
@price_change_request.remove_reminder_times :one_hour_after, :ten_minutes_before
...以便您可以执行以下操作:
class PriceReminderWorker
include Sidekiq::Worker
sidekiq_options queue: 'price_reminders', retry: true
attr_accessor *%w(
price_change_id
user
data
).freeze
delegate *%w(
reminder_time_names
), to: :price_change_request
def perform(price_change_id, reminder, user, data)
@price_change_id = price_change_id
@user = user
@data = data
reminder_time_names.each do |reminder_time_name|
send("send_#{reminder_time_name}_reminder")
end if price_change_request
end
private
def user_hash
{
to: Phonelib.parse(user.mobile_number).full_e164,
company_id: user&.company&.id,
user_name: user.first_name,
admin_user_name: data[:from_admin_user],
body: Sms::Message::priceChangeMessage.new(data).build
}
end
def send_ten_minutes_before_reminder
reminderMailer.notify(user, data).deliver_later unless price_change.cancelled_at
end
def send_one_hour_after_reminder
Sms::priceChangeSms.new(user_hash).submit unless price_change.cancelled_at
end
def price_change_request
@price_change_request ||= PriceChangeRequest.find(price_change_id)
end
end