active_delivery 1.1.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/README.md +53 -21
- data/lib/.rbnext/3.0/abstract_notifier/async_adapters/active_job.rb +2 -2
- data/lib/.rbnext/3.0/abstract_notifier/base.rb +4 -4
- data/lib/.rbnext/3.0/active_delivery/base.rb +8 -8
- data/lib/.rbnext/3.0/active_delivery/lines/base.rb +4 -4
- data/lib/.rbnext/3.0/active_delivery/testing/minitest.rb +58 -0
- data/lib/.rbnext/3.0/active_delivery/testing.rb +1 -0
- data/lib/.rbnext/3.1/abstract_notifier/async_adapters/active_job.rb +2 -2
- data/lib/.rbnext/3.1/abstract_notifier/base.rb +4 -4
- data/lib/.rbnext/3.1/active_delivery/base.rb +8 -8
- data/lib/.rbnext/3.1/active_delivery/lines/base.rb +4 -4
- data/lib/.rbnext/3.1/active_delivery/testing/minitest.rb +58 -0
- data/lib/.rbnext/3.2/abstract_notifier/async_adapters/active_job.rb +36 -0
- data/lib/.rbnext/3.2/abstract_notifier/base.rb +223 -0
- data/lib/.rbnext/3.2/abstract_notifier/testing/rspec.rb +164 -0
- data/lib/.rbnext/3.2/abstract_notifier/testing.rb +53 -0
- data/lib/.rbnext/3.2/active_delivery/base.rb +249 -0
- data/lib/.rbnext/3.2/active_delivery/lines/base.rb +101 -0
- data/lib/.rbnext/3.2/active_delivery/lines/notifier.rb +57 -0
- data/lib/.rbnext/3.2/active_delivery/testing/rspec.rb +222 -0
- data/lib/abstract_notifier/async_adapters/active_job.rb +2 -2
- data/lib/abstract_notifier/base.rb +4 -4
- data/lib/abstract_notifier/testing/minitest.rb +1 -1
- data/lib/abstract_notifier/testing/rspec.rb +4 -4
- data/lib/abstract_notifier/testing.rb +2 -2
- data/lib/active_delivery/base.rb +8 -8
- data/lib/active_delivery/lines/base.rb +4 -4
- data/lib/active_delivery/lines/notifier.rb +6 -6
- data/lib/active_delivery/testing/minitest.rb +58 -0
- data/lib/active_delivery/testing/rspec.rb +4 -4
- data/lib/active_delivery/testing.rb +1 -0
- data/lib/active_delivery/version.rb +1 -1
- metadata +17 -6
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: d05087cb016af8444f7668b81681675248b7b63f41f77a1d9fdb22b65ccb6845
         | 
| 4 | 
            +
              data.tar.gz: d60851ccb9d9ea6557d131289942edf57b39c79a499e37d41f8f1d06b480446f
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 5a94a2fd3e2f19d9e99c0df6494752b23649802b064b390ea50d65506b01beb57650f31f5cd140495d6befa847a65423cc141ec8c313a6a116de69a4cd5576df
         | 
| 7 | 
            +
              data.tar.gz: 4febe7f49e314d27f370642fa43085c5020dae8bac7fa9a3512514a6b861d17b726d4685ed91f081eab22f4c2af68a4117d37f8f29a576c78fe323f2c73b58e2
         | 
    
        data/CHANGELOG.md
    CHANGED
    
    | @@ -2,6 +2,10 @@ | |
| 2 2 |  | 
| 3 3 | 
             
            ## master
         | 
| 4 4 |  | 
| 5 | 
            +
            ## 1.2.0 (2024-02-05)
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            - Add Minitest assertions (`assert_deliveries`, `assert_no_deliveries`, `assert_delivery_enqueued`). ([@palkan][])
         | 
| 8 | 
            +
             | 
| 5 9 | 
             
            ## 1.1.0 (2023-12-01) ❄️
         | 
| 6 10 |  | 
| 7 11 | 
             
            - Support delayed delivery options (e.g, `wait_until`). ([@palkan][])
         | 
    
        data/README.md
    CHANGED
    
    | @@ -10,6 +10,8 @@ Since v1.0, Active Delivery is bundled with [Abstract Notifier](https://github.c | |
| 10 10 |  | 
| 11 11 | 
             
            📖 Read the introduction post: ["Crafting user notifications in Rails with Active Delivery"](https://evilmartians.com/chronicles/crafting-user-notifications-in-rails-with-active-delivery)
         | 
| 12 12 |  | 
| 13 | 
            +
            📖 Read more about designing notifications layer in Ruby on Rails applications in the [Layered design for Ruby on Rails applications](https://www.packtpub.com/product/layered-design-for-ruby-on-rails-applications/9781801813785) book.
         | 
| 14 | 
            +
             | 
| 13 15 | 
             
            <a href="https://evilmartians.com/?utm_source=action_policy">
         | 
| 14 16 | 
             
            <img src="https://evilmartians.com/badges/sponsored-by-evil-martians.svg" alt="Sponsored by Evil Martians" width="236" height="54"></a>
         | 
| 15 17 |  | 
| @@ -56,7 +58,7 @@ end | |
| 56 58 | 
             
            Add this line to your application's Gemfile:
         | 
| 57 59 |  | 
| 58 60 | 
             
            ```ruby
         | 
| 59 | 
            -
            gem "active_delivery", "1.0 | 
| 61 | 
            +
            gem "active_delivery", "~> 1.0"
         | 
| 60 62 | 
             
            ```
         | 
| 61 63 |  | 
| 62 64 | 
             
            And then execute:
         | 
| @@ -291,17 +293,36 @@ MyDeliver.notify(:something_wicked_this_way_comes) | |
| 291 293 |  | 
| 292 294 | 
             
            ## Testing
         | 
| 293 295 |  | 
| 294 | 
            -
             | 
| 296 | 
            +
            ### Setup
         | 
| 297 | 
            +
             | 
| 298 | 
            +
            Test mode is activated automatically if `RAILS_ENV` or `RACK_ENV` env variable is equal to "test". Otherwise, add `require "active_delivery/testing/rspec"` to your `spec_helper.rb` / `rails_helper.rb` manually or `require "active_delivery/testing/minitest"`. This is also required if you're using Spring in the test environment (e.g. with help of [spring-commands-rspec](https://github.com/jonleighton/spring-commands-rspec)).
         | 
| 299 | 
            +
             | 
| 300 | 
            +
            For Minitest, you also MUST include the test helper into your test class. For example:
         | 
| 301 | 
            +
             | 
| 302 | 
            +
            ```ruby
         | 
| 303 | 
            +
            class ActiveSupport::TestCase
         | 
| 304 | 
            +
              # ...
         | 
| 305 | 
            +
              include ActiveDelivery::TestHelper
         | 
| 306 | 
            +
            end
         | 
| 307 | 
            +
            ```
         | 
| 295 308 |  | 
| 296 309 | 
             
            ### Deliveries
         | 
| 297 310 |  | 
| 298 | 
            -
            Active Delivery provides an elegant way to test deliveries in your code (i.e., when you want to check whether a notification has been sent) through a `have_delivered_to` matcher:
         | 
| 311 | 
            +
            Active Delivery provides an elegant way to test deliveries in your code (i.e., when you want to check whether a notification has been sent) through a `have_delivered_to` RSpec matcher or `assert_delivery_enqueued` Minitest assertion:
         | 
| 299 312 |  | 
| 300 313 | 
             
            ```ruby
         | 
| 314 | 
            +
            # RSpec
         | 
| 301 315 | 
             
            it "delivers notification" do
         | 
| 302 316 | 
             
              expect { subject }.to have_delivered_to(Community::EventsDelivery, :modified, event)
         | 
| 303 317 | 
             
                .with(profile: profile)
         | 
| 304 318 | 
             
            end
         | 
| 319 | 
            +
             | 
| 320 | 
            +
            # Minitest
         | 
| 321 | 
            +
            def test_delivers_notification
         | 
| 322 | 
            +
              assert_delivery_enqueued(Community::EventsDelivery, :modified, with: [event]) do
         | 
| 323 | 
            +
                some_action
         | 
| 324 | 
            +
              end
         | 
| 325 | 
            +
            end
         | 
| 305 326 | 
             
            ```
         | 
| 306 327 |  | 
| 307 328 | 
             
            You can also use such RSpec features as compound expectations and composed matchers:
         | 
| @@ -320,14 +341,27 @@ end | |
| 320 341 | 
             
            If you want to test that no notification is delivered you can use negation
         | 
| 321 342 |  | 
| 322 343 | 
             
            ```ruby
         | 
| 344 | 
            +
            # RSpec
         | 
| 323 345 | 
             
            specify "when event is not found" do
         | 
| 324 346 | 
             
              expect do
         | 
| 325 347 | 
             
                described_class.perform_now(profile.id, "123", "one_hour_before")
         | 
| 326 348 | 
             
              end.not_to have_delivered_to(Community::EventsDelivery)
         | 
| 327 349 | 
             
            end
         | 
| 350 | 
            +
             | 
| 351 | 
            +
            # Minitest
         | 
| 352 | 
            +
            def test_no_notification_if_event_is_not_found
         | 
| 353 | 
            +
              assert_no_deliveries do
         | 
| 354 | 
            +
                some_action
         | 
| 355 | 
            +
              end
         | 
| 356 | 
            +
             | 
| 357 | 
            +
              # Alternatively, you can use the positive assertion
         | 
| 358 | 
            +
              assert_deliveries(0) do
         | 
| 359 | 
            +
                some_action
         | 
| 360 | 
            +
              end
         | 
| 361 | 
            +
            end
         | 
| 328 362 | 
             
            ```
         | 
| 329 363 |  | 
| 330 | 
            -
             | 
| 364 | 
            +
            With RSpec, you can also use the `#have_not_delivered_to` matcher:
         | 
| 331 365 |  | 
| 332 366 | 
             
            ```ruby
         | 
| 333 367 | 
             
            specify "when event is not found" do
         | 
| @@ -360,7 +394,7 @@ describe PostsDelivery do | |
| 360 394 | 
             
            end
         | 
| 361 395 | 
             
            ```
         | 
| 362 396 |  | 
| 363 | 
            -
            You can also use the `#deliver_via`  | 
| 397 | 
            +
            You can also use the `#deliver_via` RSpec matcher as follows:
         | 
| 364 398 |  | 
| 365 399 | 
             
            ```ruby
         | 
| 366 400 | 
             
            describe PostsDelivery, type: :delivery do
         | 
| @@ -387,8 +421,6 @@ describe PostsDelivery, type: :delivery do | |
| 387 421 | 
             
            end
         | 
| 388 422 | 
             
            ```
         | 
| 389 423 |  | 
| 390 | 
            -
            **NOTE:** test mode activated automatically if `RAILS_ENV` or `RACK_ENV` env variable is equal to "test". Otherwise, add `require "active_delivery/testing/rspec"` to your `spec_helper.rb` / `rails_helper.rb` manually. This is also required if you're using Spring in the test environment (e.g. with help of [spring-commands-rspec](https://github.com/jonleighton/spring-commands-rspec)).
         | 
| 391 | 
            -
             | 
| 392 424 | 
             
            ## Custom "lines"
         | 
| 393 425 |  | 
| 394 426 | 
             
            The _Line_ class describes the way you want to _transfer_ your deliveries.
         | 
| @@ -410,8 +442,8 @@ class EventPigeon | |
| 410 442 | 
             
                alias_method :with, :new
         | 
| 411 443 |  | 
| 412 444 | 
             
                # delegate delivery action to the instance
         | 
| 413 | 
            -
                def message_arrived(* | 
| 414 | 
            -
                  new.message_arrived(* | 
| 445 | 
            +
                def message_arrived(*)
         | 
| 446 | 
            +
                  new.message_arrived(*)
         | 
| 415 447 | 
             
                end
         | 
| 416 448 | 
             
              end
         | 
| 417 449 |  | 
| @@ -447,17 +479,17 @@ class PigeonLine < ActiveDelivery::Lines::Base | |
| 447 479 | 
             
              # Called when we want to send message synchronously
         | 
| 448 480 | 
             
              # `sender` here either `sender_class` or `sender_class.with(params)`
         | 
| 449 481 | 
             
              # if params passed.
         | 
| 450 | 
            -
              def notify_now(sender, delivery_action,  | 
| 482 | 
            +
              def notify_now(sender, delivery_action, *, **)
         | 
| 451 483 | 
             
                # For example, our EventPigeon class returns some `Pigeon` object
         | 
| 452 | 
            -
                pigeon = sender.public_send(delivery_action,  | 
| 484 | 
            +
                pigeon = sender.public_send(delivery_action, *, **)
         | 
| 453 485 | 
             
                # PigeonLaunchService do all the sending job
         | 
| 454 486 | 
             
                PigeonService.launch pigeon
         | 
| 455 487 | 
             
              end
         | 
| 456 488 |  | 
| 457 489 | 
             
              # Called when we want to send a message asynchronously.
         | 
| 458 490 | 
             
              # For example, you can use a background job here.
         | 
| 459 | 
            -
              def notify_later(sender, delivery_action,  | 
| 460 | 
            -
                pigeon = sender.public_send(delivery_action,  | 
| 491 | 
            +
              def notify_later(sender, delivery_action, *, **)
         | 
| 492 | 
            +
                pigeon = sender.public_send(delivery_action, *, **)
         | 
| 461 493 | 
             
                # PigeonLaunchService do all the sending job
         | 
| 462 494 | 
             
                PigeonLaunchJob.perform_later pigeon
         | 
| 463 495 | 
             
              end
         | 
| @@ -475,8 +507,8 @@ class EventPigeon | |
| 475 507 | 
             
                alias_method :with, :new
         | 
| 476 508 |  | 
| 477 509 | 
             
                # delegate delivery action to the instance
         | 
| 478 | 
            -
                def message_arrived(* | 
| 479 | 
            -
                  new.message_arrived(* | 
| 510 | 
            +
                def message_arrived(*)
         | 
| 511 | 
            +
                  new.message_arrived(*)
         | 
| 480 512 | 
             
                end
         | 
| 481 513 | 
             
              end
         | 
| 482 514 |  | 
| @@ -491,18 +523,18 @@ class EventPigeon | |
| 491 523 | 
             
            end
         | 
| 492 524 |  | 
| 493 525 | 
             
            class PigeonLine < ActiveDelivery::Lines::Base
         | 
| 494 | 
            -
              def notify_later(sender, delivery_action,  | 
| 526 | 
            +
              def notify_later(sender, delivery_action, *, **kwargs)
         | 
| 495 527 | 
             
                # `to_s` is important for serialization. Unless you might have error
         | 
| 496 | 
            -
                PigeonLaunchJob.perform_later | 
| 528 | 
            +
                PigeonLaunchJob.perform_later(sender.class.to_s, delivery_action, *, **kwargs.merge(params: line.params))
         | 
| 497 529 | 
             
              end
         | 
| 498 530 | 
             
            end
         | 
| 499 531 |  | 
| 500 532 | 
             
            class PigeonLaunchJob < ActiveJob::Base
         | 
| 501 | 
            -
              def perform(sender, delivery_action,  | 
| 533 | 
            +
              def perform(sender, delivery_action, *, params: nil, **)
         | 
| 502 534 | 
             
                klass = sender.safe_constantize
         | 
| 503 535 | 
             
                handler = params ? klass.with(**params) : klass.new
         | 
| 504 536 |  | 
| 505 | 
            -
                handler.public_send(delivery_action,  | 
| 537 | 
            +
                handler.public_send(delivery_action, *, **)
         | 
| 506 538 | 
             
              end
         | 
| 507 539 | 
             
            end
         | 
| 508 540 | 
             
            ```
         | 
| @@ -591,12 +623,12 @@ class ActionCableDeliveryLine < ActiveDelivery::Line::Base | |
| 591 623 | 
             
              # We want to broadcast all notifications
         | 
| 592 624 | 
             
              def notify?(...) = true
         | 
| 593 625 |  | 
| 594 | 
            -
              def notify_now(context, delivery_action,  | 
| 626 | 
            +
              def notify_now(context, delivery_action, *, **)
         | 
| 595 627 | 
             
                # Skip if no user provided
         | 
| 596 628 | 
             
                return unless context.user
         | 
| 597 629 |  | 
| 598 630 | 
             
                payload = {event: [context.scope, delivery_action].join(".")}
         | 
| 599 | 
            -
                payload.merge!(serialized_args( | 
| 631 | 
            +
                payload.merge!(serialized_args(*, **))
         | 
| 600 632 |  | 
| 601 633 | 
             
                DeliveryChannel.broadcast_to context.user, payload
         | 
| 602 634 | 
             
              end
         | 
| @@ -22,8 +22,8 @@ module AbstractNotifier | |
| 22 22 | 
             
                    job.set(queue: queue).perform_later(...)
         | 
| 23 23 | 
             
                  end; respond_to?(:ruby2_keywords, true) && (ruby2_keywords :enqueue)
         | 
| 24 24 |  | 
| 25 | 
            -
                  def enqueue_delivery(delivery, ** | 
| 26 | 
            -
                    job.set(queue: queue, ** | 
| 25 | 
            +
                  def enqueue_delivery(delivery, **__kwrest__)
         | 
| 26 | 
            +
                    job.set(queue: queue, **__kwrest__).perform_later(
         | 
| 27 27 | 
             
                      delivery.notifier_class.name,
         | 
| 28 28 | 
             
                      delivery.action_name,
         | 
| 29 29 | 
             
                      **delivery.delivery_params
         | 
| @@ -23,9 +23,9 @@ module AbstractNotifier | |
| 23 23 |  | 
| 24 24 | 
             
                alias_method :notification, :processed
         | 
| 25 25 |  | 
| 26 | 
            -
                def notify_later(** | 
| 26 | 
            +
                def notify_later(**__kwrest__)
         | 
| 27 27 | 
             
                  if notifier_class.async_adapter.respond_to?(:enqueue_delivery)
         | 
| 28 | 
            -
                    notifier_class.async_adapter.enqueue_delivery(self, ** | 
| 28 | 
            +
                    notifier_class.async_adapter.enqueue_delivery(self, **__kwrest__)
         | 
| 29 29 | 
             
                  else
         | 
| 30 30 | 
             
                    notifier_class.async_adapter.enqueue(notifier_class.name, action_name, params: params, args: args, kwargs: kwargs)
         | 
| 31 31 | 
             
                  end
         | 
| @@ -73,8 +73,8 @@ module AbstractNotifier | |
| 73 73 | 
             
                  end
         | 
| 74 74 | 
             
                  # rubocop:enable Style/MethodMissingSuper
         | 
| 75 75 |  | 
| 76 | 
            -
                  def respond_to_missing?(* | 
| 77 | 
            -
                    notifier_class.respond_to_missing?(* | 
| 76 | 
            +
                  def respond_to_missing?(*__rest__)
         | 
| 77 | 
            +
                    notifier_class.respond_to_missing?(*__rest__)
         | 
| 78 78 | 
             
                  end
         | 
| 79 79 | 
             
                end
         | 
| 80 80 |  | 
| @@ -77,8 +77,8 @@ module ActiveDelivery | |
| 77 77 |  | 
| 78 78 | 
             
                  # The same as .notify but delivers synchronously
         | 
| 79 79 | 
             
                  # (i.e. #deliver_now for mailers)
         | 
| 80 | 
            -
                  def notify!(mid, * | 
| 81 | 
            -
                    notify(mid, * | 
| 80 | 
            +
                  def notify!(mid, *__rest__, **hargs)
         | 
| 81 | 
            +
                    notify(mid, *__rest__, **hargs, sync: true)
         | 
| 82 82 | 
             
                  end
         | 
| 83 83 |  | 
| 84 84 | 
             
                  alias_method :notify_now, :notify!
         | 
| @@ -93,7 +93,7 @@ module ActiveDelivery | |
| 93 93 | 
             
                    end
         | 
| 94 94 | 
             
                  end
         | 
| 95 95 |  | 
| 96 | 
            -
                  def register_line(line_id, line_class = nil, notifier: nil, ** | 
| 96 | 
            +
                  def register_line(line_id, line_class = nil, notifier: nil, **__kwrest__)
         | 
| 97 97 | 
             
                    raise ArgumentError, "A line class or notifier configuration must be provided" if line_class.nil? && notifier.nil?
         | 
| 98 98 |  | 
| 99 99 | 
             
                    # Configure Notifier
         | 
| @@ -101,7 +101,7 @@ module ActiveDelivery | |
| 101 101 | 
             
                      line_class = ActiveDelivery::Lines::Notifier
         | 
| 102 102 | 
             
                    end
         | 
| 103 103 |  | 
| 104 | 
            -
                    delivery_lines[line_id] = line_class.new(id: line_id, owner: self, ** | 
| 104 | 
            +
                    delivery_lines[line_id] = line_class.new(id: line_id, owner: self, **__kwrest__)
         | 
| 105 105 |  | 
| 106 106 | 
             
                    instance_eval <<~CODE, __FILE__, __LINE__ + 1
         | 
| 107 107 | 
             
                      def #{line_id}(val)
         | 
| @@ -152,13 +152,13 @@ module ActiveDelivery | |
| 152 152 | 
             
                    super
         | 
| 153 153 | 
             
                  end
         | 
| 154 154 |  | 
| 155 | 
            -
                  def method_missing(mid, * | 
| 155 | 
            +
                  def method_missing(mid, *__rest__, **__kwrest__)
         | 
| 156 156 | 
             
                    return super unless respond_to_missing?(mid)
         | 
| 157 157 |  | 
| 158 158 | 
             
                    # Lazily define a class method to avoid lookups
         | 
| 159 159 | 
             
                    delivers(mid)
         | 
| 160 160 |  | 
| 161 | 
            -
                    public_send(mid, * | 
| 161 | 
            +
                    public_send(mid, *__rest__, **__kwrest__)
         | 
| 162 162 | 
             
                  end
         | 
| 163 163 | 
             
                end
         | 
| 164 164 |  | 
| @@ -197,7 +197,7 @@ module ActiveDelivery | |
| 197 197 | 
             
                  super
         | 
| 198 198 | 
             
                end
         | 
| 199 199 |  | 
| 200 | 
            -
                def method_missing(mid, * | 
| 200 | 
            +
                def method_missing(mid, *__rest__, **__kwrest__)
         | 
| 201 201 | 
             
                  return super unless respond_to_missing?(mid)
         | 
| 202 202 |  | 
| 203 203 | 
             
                  # Lazily define a method to avoid future lookups
         | 
| @@ -211,7 +211,7 @@ module ActiveDelivery | |
| 211 211 | 
             
                    end
         | 
| 212 212 | 
             
                  CODE
         | 
| 213 213 |  | 
| 214 | 
            -
                  public_send(mid, * | 
| 214 | 
            +
                  public_send(mid, *__rest__, **__kwrest__)
         | 
| 215 215 | 
             
                end
         | 
| 216 216 |  | 
| 217 217 | 
             
                protected
         | 
| @@ -41,16 +41,16 @@ module ActiveDelivery | |
| 41 41 | 
             
                    notify_later(handler, mid, *__rest__, &__block__)
         | 
| 42 42 | 
             
                  end; respond_to?(:ruby2_keywords, true) && (ruby2_keywords :notify_later_with_options)
         | 
| 43 43 |  | 
| 44 | 
            -
                  def notify(mid, * | 
| 44 | 
            +
                  def notify(mid, *__rest__, params:, sync:, enqueue_options:, **__kwrest__)
         | 
| 45 45 | 
             
                    clazz = params.empty? ? handler_class : handler_class.with(**params)
         | 
| 46 46 | 
             
                    if sync
         | 
| 47 | 
            -
                      return notify_now(clazz, mid, * | 
| 47 | 
            +
                      return notify_now(clazz, mid, *__rest__, **__kwrest__)
         | 
| 48 48 | 
             
                    end
         | 
| 49 49 |  | 
| 50 50 | 
             
                    if enqueue_options.empty?
         | 
| 51 | 
            -
                      notify_later(clazz, mid, * | 
| 51 | 
            +
                      notify_later(clazz, mid, *__rest__, **__kwrest__)
         | 
| 52 52 | 
             
                    else
         | 
| 53 | 
            -
                      notify_later_with_options(clazz, enqueue_options, mid, * | 
| 53 | 
            +
                      notify_later_with_options(clazz, enqueue_options, mid, *__rest__, **__kwrest__)
         | 
| 54 54 | 
             
                    end
         | 
| 55 55 | 
             
                  end
         | 
| 56 56 |  | 
| @@ -0,0 +1,58 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module ActiveDelivery
         | 
| 4 | 
            +
              module TestHelper
         | 
| 5 | 
            +
                def assert_deliveries(count)
         | 
| 6 | 
            +
                  TestDelivery.enable { yield }
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                  assert_equal TestDelivery.store.count, count, "Expected #{count} deliveries, got #{TestDelivery.store.count}"
         | 
| 9 | 
            +
                end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                def assert_no_deliveries(&__block__) ;  assert_deliveries(0, &__block__); end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                def assert_delivery_enqueued(delivery_class, event, count: 1, params: nil, with: nil)
         | 
| 14 | 
            +
                  TestDelivery.enable { yield }
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                  deliveries = TestDelivery.store
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                  if with
         | 
| 19 | 
            +
                    args = with
         | 
| 20 | 
            +
                    kwargs = args.pop if args.last.is_a?(Hash)
         | 
| 21 | 
            +
                  end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                  matching_deliveries, _unmatching_deliveries =
         | 
| 24 | 
            +
                    deliveries.partition do |(delivery, options)|
         | 
| 25 | 
            +
                      next false if delivery_class != delivery.owner.class
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                      next false if event != delivery.notification
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                      next false if params && !hash_include?(delivery.owner.params, params)
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                      next true unless with
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                      actual_args = delivery.params
         | 
| 34 | 
            +
                      actual_kwargs = delivery.options
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                      next false unless args.each.with_index.all? do |arg, i|
         | 
| 37 | 
            +
                        arg === actual_args[i]
         | 
| 38 | 
            +
                      end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                      next false unless kwargs.all? do |k, v|
         | 
| 41 | 
            +
                        v === actual_kwargs[k]
         | 
| 42 | 
            +
                      end
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                      true
         | 
| 45 | 
            +
                    end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                  assert_equal count, matching_deliveries.count, "Expected #{count} deliveries, got #{deliveries.count}"
         | 
| 48 | 
            +
                end
         | 
| 49 | 
            +
             | 
| 50 | 
            +
                private
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                def hash_include?(haystack, needle)
         | 
| 53 | 
            +
                  needle.all? do |k, v|
         | 
| 54 | 
            +
                    haystack.key?(k) && haystack[k] == v
         | 
| 55 | 
            +
                  end
         | 
| 56 | 
            +
                end
         | 
| 57 | 
            +
              end
         | 
| 58 | 
            +
            end
         | 
| @@ -22,8 +22,8 @@ module AbstractNotifier | |
| 22 22 | 
             
                    job.set(queue: queue).perform_later(...)
         | 
| 23 23 | 
             
                  end
         | 
| 24 24 |  | 
| 25 | 
            -
                  def enqueue_delivery(delivery, ** | 
| 26 | 
            -
                    job.set(queue: queue, ** | 
| 25 | 
            +
                  def enqueue_delivery(delivery, **__kwrest__)
         | 
| 26 | 
            +
                    job.set(queue: queue, **__kwrest__).perform_later(
         | 
| 27 27 | 
             
                      delivery.notifier_class.name,
         | 
| 28 28 | 
             
                      delivery.action_name,
         | 
| 29 29 | 
             
                      **delivery.delivery_params
         | 
| @@ -23,9 +23,9 @@ module AbstractNotifier | |
| 23 23 |  | 
| 24 24 | 
             
                alias_method :notification, :processed
         | 
| 25 25 |  | 
| 26 | 
            -
                def notify_later(** | 
| 26 | 
            +
                def notify_later(**__kwrest__)
         | 
| 27 27 | 
             
                  if notifier_class.async_adapter.respond_to?(:enqueue_delivery)
         | 
| 28 | 
            -
                    notifier_class.async_adapter.enqueue_delivery(self, ** | 
| 28 | 
            +
                    notifier_class.async_adapter.enqueue_delivery(self, **__kwrest__)
         | 
| 29 29 | 
             
                  else
         | 
| 30 30 | 
             
                    notifier_class.async_adapter.enqueue(notifier_class.name, action_name, params: params, args: args, kwargs: kwargs)
         | 
| 31 31 | 
             
                  end
         | 
| @@ -73,8 +73,8 @@ module AbstractNotifier | |
| 73 73 | 
             
                  end
         | 
| 74 74 | 
             
                  # rubocop:enable Style/MethodMissingSuper
         | 
| 75 75 |  | 
| 76 | 
            -
                  def respond_to_missing?(* | 
| 77 | 
            -
                    notifier_class.respond_to_missing?(* | 
| 76 | 
            +
                  def respond_to_missing?(*__rest__)
         | 
| 77 | 
            +
                    notifier_class.respond_to_missing?(*__rest__)
         | 
| 78 78 | 
             
                  end
         | 
| 79 79 | 
             
                end
         | 
| 80 80 |  | 
| @@ -77,8 +77,8 @@ module ActiveDelivery | |
| 77 77 |  | 
| 78 78 | 
             
                  # The same as .notify but delivers synchronously
         | 
| 79 79 | 
             
                  # (i.e. #deliver_now for mailers)
         | 
| 80 | 
            -
                  def notify!(mid, * | 
| 81 | 
            -
                    notify(mid, * | 
| 80 | 
            +
                  def notify!(mid, *__rest__, **hargs)
         | 
| 81 | 
            +
                    notify(mid, *__rest__, **hargs, sync: true)
         | 
| 82 82 | 
             
                  end
         | 
| 83 83 |  | 
| 84 84 | 
             
                  alias_method :notify_now, :notify!
         | 
| @@ -93,7 +93,7 @@ module ActiveDelivery | |
| 93 93 | 
             
                    end
         | 
| 94 94 | 
             
                  end
         | 
| 95 95 |  | 
| 96 | 
            -
                  def register_line(line_id, line_class = nil, notifier: nil, ** | 
| 96 | 
            +
                  def register_line(line_id, line_class = nil, notifier: nil, **__kwrest__)
         | 
| 97 97 | 
             
                    raise ArgumentError, "A line class or notifier configuration must be provided" if line_class.nil? && notifier.nil?
         | 
| 98 98 |  | 
| 99 99 | 
             
                    # Configure Notifier
         | 
| @@ -101,7 +101,7 @@ module ActiveDelivery | |
| 101 101 | 
             
                      line_class = ActiveDelivery::Lines::Notifier
         | 
| 102 102 | 
             
                    end
         | 
| 103 103 |  | 
| 104 | 
            -
                    delivery_lines[line_id] = line_class.new(id: line_id, owner: self, ** | 
| 104 | 
            +
                    delivery_lines[line_id] = line_class.new(id: line_id, owner: self, **__kwrest__)
         | 
| 105 105 |  | 
| 106 106 | 
             
                    instance_eval <<~CODE, __FILE__, __LINE__ + 1
         | 
| 107 107 | 
             
                      def #{line_id}(val)
         | 
| @@ -152,13 +152,13 @@ module ActiveDelivery | |
| 152 152 | 
             
                    super
         | 
| 153 153 | 
             
                  end
         | 
| 154 154 |  | 
| 155 | 
            -
                  def method_missing(mid, * | 
| 155 | 
            +
                  def method_missing(mid, *__rest__, **__kwrest__)
         | 
| 156 156 | 
             
                    return super unless respond_to_missing?(mid)
         | 
| 157 157 |  | 
| 158 158 | 
             
                    # Lazily define a class method to avoid lookups
         | 
| 159 159 | 
             
                    delivers(mid)
         | 
| 160 160 |  | 
| 161 | 
            -
                    public_send(mid, * | 
| 161 | 
            +
                    public_send(mid, *__rest__, **__kwrest__)
         | 
| 162 162 | 
             
                  end
         | 
| 163 163 | 
             
                end
         | 
| 164 164 |  | 
| @@ -197,7 +197,7 @@ module ActiveDelivery | |
| 197 197 | 
             
                  super
         | 
| 198 198 | 
             
                end
         | 
| 199 199 |  | 
| 200 | 
            -
                def method_missing(mid, * | 
| 200 | 
            +
                def method_missing(mid, *__rest__, **__kwrest__)
         | 
| 201 201 | 
             
                  return super unless respond_to_missing?(mid)
         | 
| 202 202 |  | 
| 203 203 | 
             
                  # Lazily define a method to avoid future lookups
         | 
| @@ -211,7 +211,7 @@ module ActiveDelivery | |
| 211 211 | 
             
                    end
         | 
| 212 212 | 
             
                  CODE
         | 
| 213 213 |  | 
| 214 | 
            -
                  public_send(mid, * | 
| 214 | 
            +
                  public_send(mid, *__rest__, **__kwrest__)
         | 
| 215 215 | 
             
                end
         | 
| 216 216 |  | 
| 217 217 | 
             
                protected
         | 
| @@ -41,16 +41,16 @@ module ActiveDelivery | |
| 41 41 | 
             
                    notify_later(handler, mid, ...)
         | 
| 42 42 | 
             
                  end
         | 
| 43 43 |  | 
| 44 | 
            -
                  def notify(mid, * | 
| 44 | 
            +
                  def notify(mid, *__rest__, params:, sync:, enqueue_options:, **__kwrest__)
         | 
| 45 45 | 
             
                    clazz = params.empty? ? handler_class : handler_class.with(**params)
         | 
| 46 46 | 
             
                    if sync
         | 
| 47 | 
            -
                      return notify_now(clazz, mid, * | 
| 47 | 
            +
                      return notify_now(clazz, mid, *__rest__, **__kwrest__)
         | 
| 48 48 | 
             
                    end
         | 
| 49 49 |  | 
| 50 50 | 
             
                    if enqueue_options.empty?
         | 
| 51 | 
            -
                      notify_later(clazz, mid, * | 
| 51 | 
            +
                      notify_later(clazz, mid, *__rest__, **__kwrest__)
         | 
| 52 52 | 
             
                    else
         | 
| 53 | 
            -
                      notify_later_with_options(clazz, enqueue_options, mid, * | 
| 53 | 
            +
                      notify_later_with_options(clazz, enqueue_options, mid, *__rest__, **__kwrest__)
         | 
| 54 54 | 
             
                    end
         | 
| 55 55 | 
             
                  end
         | 
| 56 56 |  | 
| @@ -0,0 +1,58 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module ActiveDelivery
         | 
| 4 | 
            +
              module TestHelper
         | 
| 5 | 
            +
                def assert_deliveries(count)
         | 
| 6 | 
            +
                  TestDelivery.enable { yield }
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                  assert_equal TestDelivery.store.count, count, "Expected #{count} deliveries, got #{TestDelivery.store.count}"
         | 
| 9 | 
            +
                end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                def assert_no_deliveries(&__block__) = assert_deliveries(0, &__block__)
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                def assert_delivery_enqueued(delivery_class, event, count: 1, params: nil, with: nil)
         | 
| 14 | 
            +
                  TestDelivery.enable { yield }
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                  deliveries = TestDelivery.store
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                  if with
         | 
| 19 | 
            +
                    args = with
         | 
| 20 | 
            +
                    kwargs = args.pop if args.last.is_a?(Hash)
         | 
| 21 | 
            +
                  end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                  matching_deliveries, _unmatching_deliveries =
         | 
| 24 | 
            +
                    deliveries.partition do |(delivery, options)|
         | 
| 25 | 
            +
                      next false if delivery_class != delivery.owner.class
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                      next false if event != delivery.notification
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                      next false if params && !hash_include?(delivery.owner.params, params)
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                      next true unless with
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                      actual_args = delivery.params
         | 
| 34 | 
            +
                      actual_kwargs = delivery.options
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                      next false unless args.each.with_index.all? do |arg, i|
         | 
| 37 | 
            +
                        arg === actual_args[i]
         | 
| 38 | 
            +
                      end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                      next false unless kwargs.all? do |k, v|
         | 
| 41 | 
            +
                        v === actual_kwargs[k]
         | 
| 42 | 
            +
                      end
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                      true
         | 
| 45 | 
            +
                    end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                  assert_equal count, matching_deliveries.count, "Expected #{count} deliveries, got #{deliveries.count}"
         | 
| 48 | 
            +
                end
         | 
| 49 | 
            +
             | 
| 50 | 
            +
                private
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                def hash_include?(haystack, needle)
         | 
| 53 | 
            +
                  needle.all? do |k, v|
         | 
| 54 | 
            +
                    haystack.key?(k) && haystack[k] == v
         | 
| 55 | 
            +
                  end
         | 
| 56 | 
            +
                end
         | 
| 57 | 
            +
              end
         | 
| 58 | 
            +
            end
         | 
| @@ -0,0 +1,36 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module AbstractNotifier
         | 
| 4 | 
            +
              module AsyncAdapters
         | 
| 5 | 
            +
                class ActiveJob
         | 
| 6 | 
            +
                  class DeliveryJob < ::ActiveJob::Base
         | 
| 7 | 
            +
                    def perform(notifier_class, ...)
         | 
| 8 | 
            +
                      AbstractNotifier::NotificationDelivery.new(notifier_class.constantize, ...).notify_now
         | 
| 9 | 
            +
                    end
         | 
| 10 | 
            +
                  end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                  DEFAULT_QUEUE = "notifiers"
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                  attr_reader :job, :queue
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                  def initialize(queue: DEFAULT_QUEUE, job: DeliveryJob)
         | 
| 17 | 
            +
                    @job = job
         | 
| 18 | 
            +
                    @queue = queue
         | 
| 19 | 
            +
                  end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                  def enqueue(...)
         | 
| 22 | 
            +
                    job.set(queue:).perform_later(...)
         | 
| 23 | 
            +
                  end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                  def enqueue_delivery(delivery, **__kwrest__)
         | 
| 26 | 
            +
                    job.set(queue:, **__kwrest__).perform_later(
         | 
| 27 | 
            +
                      delivery.notifier_class.name,
         | 
| 28 | 
            +
                      delivery.action_name,
         | 
| 29 | 
            +
                      **delivery.delivery_params
         | 
| 30 | 
            +
                    )
         | 
| 31 | 
            +
                  end
         | 
| 32 | 
            +
                end
         | 
| 33 | 
            +
              end
         | 
| 34 | 
            +
            end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
            AbstractNotifier.async_adapter ||= :active_job
         |