Coder Social home page Coder Social logo

palkan / active_delivery Goto Github PK

View Code? Open in Web Editor NEW
589.0 589.0 15.0 208 KB

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

License: MIT License

Ruby 99.60% Shell 0.14% Makefile 0.26%
hacktoberfest mailers notifications rails ruby

active_delivery's Introduction

Hey / Привет 👋

My name is Vladimir (or Вова), and I'm a principal backend engineer at @evilmartians.

📕 My book "Layered design for Ruby on Rails applications" is avalable now: Amazon | Packt

I'm working on:

Check out some of my blog posts:

...and conference talks:

active_delivery's People

Contributors

badlamer avatar benebrice avatar brovikov avatar curpeng avatar ibublik avatar kimihito avatar lokideos avatar olimart avatar palkan avatar stanislove avatar thornomad avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

active_delivery's Issues

Testing callbacks

Hi;
I'm trying to test the logic of my callbacks. I was hoping to do something like:

    subject { MyDelivery.with(with_params).notify(notification) }
...
          expect { subject }.not_to have_delivered_to(MyDelivery, notification)

but it looks like the callbacks are not actually getting called in test mode. Is that correct? Is there a different way you suggest to test my logic?

Here's what my class looks like:

class MyDelivery < ApplicationDelivery
  before_notify :check_conditions
...
  private
    def check_conditions
      if params[:only_if_unsent].present?
        return false if user.notified?(notification_name)
      end

Unable resolve mailer class different to pattern name.gsub(/Delivery$/, "Mailer")

I faced with problem when I need to notify by email several recipients with different content. So I have several Action Mailer classes for that. But I couldn't find a way how to explicitly set mailer class when I'm registering the line. It would be great to have it on the same way how we do it with ActiveDelivery::Lines::Notifier:

  register_line :merchant, ActiveDelivery::Lines::Notifier,
    resolver: ->(name) { Notifications::MerchantMailer }

To have it working - I added CustomMailer class:

module DeliveryLines
  class CustomMailer < ActiveDelivery::Lines::Notifier
    alias mailer_class handler_class

    def notify?(method_name)
      mailer_class.action_methods.include?(method_name.to_s)
    end

    def notify_now(mailer, mid, *args)
      mailer.public_send(mid, *args).deliver_now
    end

    def notify_later(mailer, mid, *args)
      mailer.public_send(mid, *args).deliver_later
    end
  end
end

It works good to me. But probably having ability to set resolver for ActiveDelivery::Lines::Mailer class on the same way how we have it at ActiveDelivery::Lines::Notifier is a good idea for improvement?

rails db:migrate RAILS_ENV=test fails when gem in installed

Hello,

When the active_delivery gem in installed, it is impossible for me to migrate my test ENV. I get this message :

NoMethodError: undefined method configure' for RSpec:Module /home/yves/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/active_delivery-0.3.0/lib/active_delivery/testing/rspec.rb:167:in

'

rails db:migrate RAILS_ENV=test --trace
/home/yves/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/faraday-0.17.0/lib/faraday/options.rb:166: warning: Capturing the given block using Proc.new is deprecated; use `&block` instead
/home/yves/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/faraday-0.17.0/lib/faraday/options.rb:166: warning: Capturing the given block using Proc.new is deprecated; use `&block` instead
/home/yves/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/faraday-0.17.0/lib/faraday/options.rb:166: warning: Capturing the given block using Proc.new is deprecated; use `&block` instead
/home/yves/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/faraday-0.17.0/lib/faraday/options.rb:166: warning: Capturing the given block using Proc.new is deprecated; use `&block` instead
/home/yves/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/faraday-0.17.0/lib/faraday/options.rb:166: warning: Capturing the given block using Proc.new is deprecated; use `&block` instead
rails aborted!
NoMethodError: undefined method `configure' for RSpec:Module
/home/yves/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/active_delivery-0.3.0/lib/active_delivery/testing/rspec.rb:167:in `<main>'
/home/yves/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in `require'
/home/yves/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in `block in require_with_bootsnap_lfi'
/home/yves/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/loaded_features_index.rb:92:in `register'
/home/yves/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:21:in `require_with_bootsnap_lfi'
/home/yves/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:30:in `require'
/home/yves/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/activesupport-6.0.1/lib/active_support/dependencies.rb:325:in `block in require'
/home/yves/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/activesupport-6.0.1/lib/active_support/dependencies.rb:291:in `load_dependency'
/home/yves/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/activesupport-6.0.1/lib/active_support/dependencies.rb:325:in `require'
/home/yves/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/active_delivery-0.3.0/lib/active_delivery/testing.rb:48:in `<main>'
/home/yves/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in `require'
/home/yves/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in `block in require_with_bootsnap_lfi'
/home/yves/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/loaded_features_index.rb:92:in `register'
/home/yves/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:21:in `require_with_bootsnap_lfi'
/home/yves/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:30:in `require'
/home/yves/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/activesupport-6.0.1/lib/active_support/dependencies.rb:325:in `block in require'
/home/yves/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/activesupport-6.0.1/lib/active_support/dependencies.rb:291:in `load_dependency'
/home/yves/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/activesupport-6.0.1/lib/active_support/dependencies.rb:325:in `require'
/home/yves/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/active_delivery-0.3.0/lib/active_delivery.rb:10:in `<main>'
/home/yves/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in `require'
/home/yves/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in `block in require_with_bootsnap_lfi'
/home/yves/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/loaded_features_index.rb:92:in `register'
/home/yves/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:21:in `require_with_bootsnap_lfi'
/home/yves/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:30:in `require'
/home/yves/.rbenv/versions/2.7.0/lib/ruby/2.7.0/bundler/runtime.rb:74:in `block (2 levels) in require'
/home/yves/.rbenv/versions/2.7.0/lib/ruby/2.7.0/bundler/runtime.rb:69:in `each'
/home/yves/.rbenv/versions/2.7.0/lib/ruby/2.7.0/bundler/runtime.rb:69:in `block in require'
/home/yves/.rbenv/versions/2.7.0/lib/ruby/2.7.0/bundler/runtime.rb:58:in `each'
/home/yves/.rbenv/versions/2.7.0/lib/ruby/2.7.0/bundler/runtime.rb:58:in `require'
/home/yves/.rbenv/versions/2.7.0/lib/ruby/2.7.0/bundler.rb:174:in `require'
/home/yves/calaundry/config/application.rb:7:in `<main>'
/home/yves/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in `require'
/home/yves/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in `block in require_with_bootsnap_lfi'
/home/yves/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/loaded_features_index.rb:92:in `register'
/home/yves/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:21:in `require_with_bootsnap_lfi'
/home/yves/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:30:in `require'
/home/yves/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/activesupport-6.0.1/lib/active_support/dependencies.rb:325:in `block in require'
/home/yves/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/activesupport-6.0.1/lib/active_support/dependencies.rb:291:in `load_dependency'
/home/yves/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/activesupport-6.0.1/lib/active_support/dependencies.rb:325:in `require'
/home/yves/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:48:in `require_relative'
/home/yves/calaundry/Rakefile:4:in `<main>'
/home/yves/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:54:in `load'
/home/yves/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:54:in `load'
/home/yves/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/activesupport-6.0.1/lib/active_support/dependencies.rb:319:in `block in load'
/home/yves/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/activesupport-6.0.1/lib/active_support/dependencies.rb:291:in `load_dependency'
/home/yves/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/activesupport-6.0.1/lib/active_support/dependencies.rb:319:in `load'
/home/yves/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/rake-13.0.1/lib/rake/rake_module.rb:29:in `load_rakefile'
/home/yves/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/rake-13.0.1/lib/rake/application.rb:703:in `raw_load_rakefile'
/home/yves/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/rake-13.0.1/lib/rake/application.rb:104:in `block in load_rakefile'
/home/yves/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/rake-13.0.1/lib/rake/application.rb:186:in `standard_exception_handling'
/home/yves/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/rake-13.0.1/lib/rake/application.rb:103:in `load_rakefile'
/home/yves/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/railties-6.0.1/lib/rails/commands/rake/rake_command.rb:22:in `block in perform'
/home/yves/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/rake-13.0.1/lib/rake/application.rb:186:in `standard_exception_handling'
/home/yves/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/railties-6.0.1/lib/rails/commands/rake/rake_command.rb:20:in `perform'
/home/yves/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/railties-6.0.1/lib/rails/command.rb:48:in `invoke'
/home/yves/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/railties-6.0.1/lib/rails/commands.rb:18:in `<main>'
/home/yves/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in `require'
/home/yves/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in `block in require_with_bootsnap_lfi'
/home/yves/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/loaded_features_index.rb:92:in `register'
/home/yves/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:21:in `require_with_bootsnap_lfi'
/home/yves/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:30:in `require'
/home/yves/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/activesupport-6.0.1/lib/active_support/dependencies.rb:325:in `block in require'
/home/yves/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/activesupport-6.0.1/lib/active_support/dependencies.rb:291:in `load_dependency'
/home/yves/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/activesupport-6.0.1/lib/active_support/dependencies.rb:325:in `require'
/home/yves/calaundry/bin/rails:9:in `<top (required)>'
/home/yves/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/spring-2.1.0/lib/spring/client/rails.rb:28:in `load'
/home/yves/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/spring-2.1.0/lib/spring/client/rails.rb:28:in `call'
/home/yves/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/spring-2.1.0/lib/spring/client/command.rb:7:in `call'
/home/yves/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/spring-2.1.0/lib/spring/client.rb:30:in `run'
/home/yves/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/spring-2.1.0/bin/spring:49:in `<top (required)>'
/home/yves/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/spring-2.1.0/lib/spring/binstub.rb:11:in `load'
/home/yves/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/spring-2.1.0/lib/spring/binstub.rb:11:in `<top (required)>'
/home/yves/.rbenv/versions/2.7.0/lib/ruby/2.7.0/rubygems/core_ext/kernel_require.rb:72:in `require'
/home/yves/.rbenv/versions/2.7.0/lib/ruby/2.7.0/rubygems/core_ext/kernel_require.rb:72:in `require'
/home/yves/calaundry/bin/spring:15:in `<top (required)>'
bin/rails:3:in `load'
bin/rails:3:in `<main>'

I solved the problem by removing the gem from the gemfile for the moment.
Thanks for your help.
Texicitys

have_not_delivered_to matcher for specs

Hi!
How about to add have_not_deliverd_to matcher?
This would allow me to rewrite my code

from

it "doesn't send notification to listener" do
   expect { subject }.not_to have_delivered_to(EventDelivery, :notify_listener)
end

it "doesn't send notification to manager" do
   expect { subject }.not_to have_delivered_to(EventDelivery, :notify_manager)
end

to

it "doesn't send notifications to listener and manager" do
   expect { subject }.to have_not_delivered_to(EventDelivery, :notify_listener)
                     .and have_not_delivered_to(EventDelivery, :notify_manager)
end

notify_later with parameters to schedule it

Is your feature request related to a problem? Please describe.

Schedule a delivery like action mailer

Describe the solution you'd like

MyDelivery.with(user: u).notify(:something, {wait_until: 1.minute.from_now})

Describe alternatives you've considered

I'm wondering if it's currently possible or not. I did not find any clue on the documentation. From the code I've read, it seams possible but not found the correct way to write it. @palkan I'm pretty sure you know everything about this subject. Could you light this up? 😁

How to send conditionally to different lines

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?

Callbacks for specific notification

Hi guys,

Thanks for implementing this gem, it's super helpful!
There is one thing, which seems to be really nice to have - an option to specify the name of the notification for a callback. It turned out that quite often, we need to do something only for specific notification. Right now, we have two options:

QuestionsDelivery < ApplicationDelivery
   after_notify :mark_question_as_sent 
  
   after_notify do
     # Option 2: check notification_name and call needed actions
      mark_question_as_sent if notification_name == :send_questions
      create_event if notification_name == :questions_reminder
   end

  private

  def mark_question_as_sent
    # Option 1: another notification doesn't need a question object, e.g. it's a reminder to a user that we can send questions, so we can just check if params[:question] is present. 
     return unless params[:question].present? 
  end
end

As you see, both solutions look hacky, it would be nice to have something like:

  after_notify :mark_question_as_sent, only: %[questions_sent]

ActiveDelivery::TestDelivery does not work with fibers

The ActiveDelivery::TestDelivery module user fiber-local storage to store its state. This makes its behavior break when using rspec matchers to test a delivery done in a fiber.

Steps to reproduce

class SomeDelivery < ActiveDelivery::Base
end

RSpec.describe SomeDelivery do
  it 'works with fibers' do
    expect do
      Fiber.new { SomeDelivery.notify!(:event) }.resume
    end.to have_delivered_to(SomeDelivery, :event)
  end
end

Actual Behavior

Failures:

  1) SomeDelivery works with fibers
     Failure/Error:
       expect do
         Fiber.new { SomeDelivery.notify!(:event) }.resume
       end.to have_delivered_to(SomeDelivery, :event)

       expected to deliver :event notification via SomeDelivery with:
        - args: <none>
       exactly once, but haven't delivered anything
     # ./spec/some_delivery.rb:8:in `block (2 levels) in <top (required)>'

Expected behaviour

Finished in 0.09412 seconds (files took 2.25 seconds to load)
1 example, 0 failures

Comments

This is behavior is related to the usage of Thread#[] and Thread#[]= to set the TestModule internal state which are both fiber-local.

I believe this is not the intended behavior and could be fixed by using Thread#thread_variable_set and Thread#thread_variable_get methods.

In any case if you think this is worth fixing I can open a pull request for this.

Spec matcher for callbacks

Is your feature request related to a problem? Please describe.

With inheritance, if becomes more and more complicated to test callbacks correctly. A dedicated matcher could help a lot with that.

Describe the solution you'd like

describe '#initialize' do
  let(:service) { MyDelivery.with(foo: :bar) }
 
  it 'has `baz` callback' do
    expect(service).to have_active_callback(:baz)
                                       .with_action(:before)
                                       .on(:mailer)
                                       .only_for(:foo_bar)
                                       .and_return(true)
  end
end

Describe alternatives you've considered

Unless, you need to test every single clauses manually for each method called.

skip callback

Is your feature request related to a problem? Please describe.

If you want to avoid a callback for a specific method, skip is not implemented

Describe the solution you'd like

Something like AbstractController::Callbacks

Describe alternatives you've considered

Currently, the only solution to do that is to redefine the callback on the child class and use except.

Syntax error: Anonymous arguments don't support in Ruby 3.1

What did you do?

Because Anonymous args supports since Ruby 3.2, syntax error occur in Ruby 3.1.

notifier_class.async_adapter.enqueue_delivery(self, **)

https://rubyreferences.github.io/rubychanges/3.2.html#anonymous-arguments-passing-improvements

What did you expect to happen?

N/A

What actually happened?

N/A

Additional context

N/A

Environment

Ruby Version:

3.1

Framework Version (Rails, whatever):

N/A

Active Delivery Version:

1.2.0

"notify_later" on new line is a bit tricky

Is your feature request related to a problem? Please describe.

On new line implementation, I figured out that example given is not working perfectly with parameterized mailer/line

Describe the solution you'd like

# `kwargs.merge(line.params)` is the path I found
def notify_later(line, delivery_action, *args, **kwargs)
  NewLineJob.perform_later line.class, delivery_action, *args, **kwargs.merge(line.params)
end

unless this, we cannot handle parametrized value on class method. Here is my second implementation on the new line

class NewLine
    attr_reader :params

    class << self
      ##
      # Class method to init (for async) and call the instance method
      def my_method(*args)
        with(args.last).my_method
      end
   end

  def initialize(params = {})
      @params = params
      # Do something else with params
    end
  end
end

Describe alternatives you've considered

I'm not 100% sure this works in all cases. Can you confirm with the whole gem knowledge
@palkan ?
In my case it's not a problem because all my mailers are parameterized (adding tracking headers) but I did not check with non-parameterized method after this fix.

RSpec matchers doesn't work

When I try to use negated matcher in RSpec, I get the following error:

Failure/Error: expect { subject }.to have_not_delivered_to(MyDelivery)
       You must pass an argument rather than a block to use the provided matcher (have not delivered to MyDelivery), or the matcher must implement `supports_block_expectations?`.

The reason in method lookup path and matcher's name which leads to this point:
https://github.com/rspec/rspec-expectations/blob/33e3c614f82be81f81e09f8725b6bc450f7c40d0/lib/rspec/matchers.rb#L962-L963

Would love to send PR with fix if you give me a hint :)

UPDATED: problem is not only with negated matchers, but with all RSpec matchers

resolve_class definition changed

What did you do?

Upgrade from 0.4.4 to 1.0.0

What did you expect to happen?

Nothing breaking

What actually happened?

Breaking change on resolve_class definition for new delivery method.

Additional context

# before "name" was a String
def resolve_class(name)
    name.gsub(/Delivery$/, 'Pusher').safe_constantize
end

# after "name" is a Class
def resolve_class(name)
    name.to_s.gsub(/Delivery$/, 'Pusher').safe_constantize
end

@palkan Is that a normal update? Maybe if it's breaking we can add it to the change log?

Environment

Ruby Version: 2.7.2

Framework Version (Rails, whatever): 6.1.7.6

Active Delivery Version: 1.0.0

Folders structure

Hi, how would you suggests folders to be organized for deliveries and lines? something like app/deliveries and app/services/lines?
I know it's completely up to the developer, but I wonder whether you have a pattern to suggest for structuring this better!
Thanks

Side effects of upgrade to Ruby 2.7 and Rails 7 with have_delivered_to and a_hash_including

What did you do?

Upgrade from 0.4.4 to 1.0.0

What did you expect to happen?

Nothing breaking

What actually happened?

Failure on specs for have_delivered_to used with a_hash_including

Additional context

expect { subject.do_something }
        .to have_delivered_to(V1::SomeDelivery, :do_something).with(
          a_hash_including(foo: :bar)
        )

Error raised:

expected to deliver :do_something notification via V1::SomeDelivery with:

  • params: a stash including {:foo => :bar}
  • args: < none >

exactly once, but delivered the following unexpected notifications:

  • params: {:foo => :bar}
  • args: []
  • kwargs: {}

Environment

Ruby Version: 2.7.2

Framework Version (Rails, whatever): 6.1.7.6

Active Delivery Version: 1.0.0

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.