palkan / active_delivery

Ruby framework for keeping all types of notifications (mailers, push notifications, whatever) in one place

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

How to send conditionally to different lines

hbhanoo opened this issue · comments

Hi guys,
I'm still working through my usecase.
My users can receive either email or sms notifications depending on whether or not they have provided an (email, phone), as well as how they have set up their preferences.

I've thought of modeling this several ways, none of which seem currently supported in the code. But I figure I must be misunderstanding something, since it seems like this is the problem you set out to solve in the first place.

Here's what I came up with:

conditional execution of Lines:

class ApplicationDelivery
  before_notify { raise ArgumentError, 'need user' unless params[:user].present? }
  register_line :email, if: ->() { params[:user].email.present? }
  register_line :sms, if: ->() { params[:user].phone.present? }
end

or halting execution within the line itself:

# This works right now:
class ApplicationMailer  < ActionMailer::Base
    before_action do |mail|
      if !params[:recipient].email.present?
        # Callbacks for mailers are implemented using AbstractController::Callbacks
        # This sets up a 'terminator' of:
        # result_lambda.call; controller.performed?
        # AbstractController::Base sets performed? as: 'response_body'
        # So - as soon as we set a response body, no other callbacks or actions will occur.
        # So - in addition to suppressing deliveries for this mail, we will also set a response body
        # so that no further callbacks (or the action itself) get performed, thereby stopping processing.
        mail.perform_deliveries = false
        mail.response_body = "DO_NOT_DELIVER"
      end
    end
end

# but AbstractNotifier doesn't seem to support callbacks
class ApplicationSms < AbstractNotifier::Base
  before_action do
   # assuming a callback implementation with a terminator that checks for false return value
   return params[:recipient].phone.present? 
  end
end

What am I missing?

What am I missing?

Sounds like the following code solves the problem (per-line callbacks):

class ApplicationDelivery < ActiveDelivery::Base
  before_notify { raise ArgumentError, 'need user' unless params[:user].present? }

  # specify callback for a particular line
  before_notify :ensure_email_recipient, on: :mailer
  before_notify :ensure_phone_recipient, on: :sms

  private

  def ensure_email_recipient
    params[:recipient].email.present?
  end
end

That almost the exact code we have in our base delivery classes.

ugh. Now that I read your comment I can see the line-specific callbacks implemented in the code! Sorry about that. I just couldn't see that.