README.md in active_delivery-1.1.0 vs README.md in active_delivery-1.2.0
- old
+ new
@@ -8,10 +8,12 @@
Since v1.0, Active Delivery is bundled with [Abstract Notifier](https://github.com/palkan/abstract_notifier). See the docs on how to create custom notifiers [below](#abstract-notifier).
📖 Read the introduction post: ["Crafting user notifications in Rails with Active Delivery"](https://evilmartians.com/chronicles/crafting-user-notifications-in-rails-with-active-delivery)
+📖 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.
+
<a href="https://evilmartians.com/?utm_source=action_policy">
<img src="https://evilmartians.com/badges/sponsored-by-evil-martians.svg" alt="Sponsored by Evil Martians" width="236" height="54"></a>
Requirements:
@@ -54,11 +56,11 @@
## Installation
Add this line to your application's Gemfile:
```ruby
-gem "active_delivery", "1.0.0.rc2"
+gem "active_delivery", "~> 1.0"
```
And then execute:
```sh
@@ -289,21 +291,40 @@
#=> Delivery triggered: something_wicked_this_way_comes
```
## Testing
-**NOTE:** Currently, only RSpec matchers are provided.
+### Setup
+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)).
+
+For Minitest, you also MUST include the test helper into your test class. For example:
+
+```ruby
+class ActiveSupport::TestCase
+ # ...
+ include ActiveDelivery::TestHelper
+end
+```
+
### Deliveries
-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:
+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:
```ruby
+# RSpec
it "delivers notification" do
expect { subject }.to have_delivered_to(Community::EventsDelivery, :modified, event)
.with(profile: profile)
end
+
+# Minitest
+def test_delivers_notification
+ assert_delivery_enqueued(Community::EventsDelivery, :modified, with: [event]) do
+ some_action
+ end
+end
```
You can also use such RSpec features as compound expectations and composed matchers:
```ruby
@@ -318,18 +339,31 @@
```
If you want to test that no notification is delivered you can use negation
```ruby
+# RSpec
specify "when event is not found" do
expect do
described_class.perform_now(profile.id, "123", "one_hour_before")
end.not_to have_delivered_to(Community::EventsDelivery)
end
+
+# Minitest
+def test_no_notification_if_event_is_not_found
+ assert_no_deliveries do
+ some_action
+ end
+
+ # Alternatively, you can use the positive assertion
+ assert_deliveries(0) do
+ some_action
+ end
+end
```
-or use the `#have_not_delivered_to` matcher:
+With RSpec, you can also use the `#have_not_delivered_to` matcher:
```ruby
specify "when event is not found" do
expect do
described_class.perform_now(profile.id, "123", "one_hour_before")
@@ -358,11 +392,11 @@
end
end
end
```
-You can also use the `#deliver_via` matchers as follows:
+You can also use the `#deliver_via` RSpec matcher as follows:
```ruby
describe PostsDelivery, type: :delivery do
let(:user) { build_stubbed(:user) }
let(:post) { build_stubbed(:post) }
@@ -385,12 +419,10 @@
end
end
end
```
-**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)).
-
## Custom "lines"
The _Line_ class describes the way you want to _transfer_ your deliveries.
We only provide only Action Mailer _line_ out-of-the-box.
@@ -408,12 +440,12 @@
class << self
# Add `.with` method as an alias
alias_method :with, :new
# delegate delivery action to the instance
- def message_arrived(*args)
- new.message_arrived(*args)
+ def message_arrived(*)
+ new.message_arrived(*)
end
end
def initialize(params = {})
# do smth with params
@@ -445,21 +477,21 @@
end
# Called when we want to send message synchronously
# `sender` here either `sender_class` or `sender_class.with(params)`
# if params passed.
- def notify_now(sender, delivery_action, *args, **kwargs)
+ def notify_now(sender, delivery_action, *, **)
# For example, our EventPigeon class returns some `Pigeon` object
- pigeon = sender.public_send(delivery_action, *args, **kwargs)
+ pigeon = sender.public_send(delivery_action, *, **)
# PigeonLaunchService do all the sending job
PigeonService.launch pigeon
end
# Called when we want to send a message asynchronously.
# For example, you can use a background job here.
- def notify_later(sender, delivery_action, *args, **kwargs)
- pigeon = sender.public_send(delivery_action, *args, **kwargs)
+ def notify_later(sender, delivery_action, *, **)
+ pigeon = sender.public_send(delivery_action, *, **)
# PigeonLaunchService do all the sending job
PigeonLaunchJob.perform_later pigeon
end
end
```
@@ -473,12 +505,12 @@
class << self
# Add `.with` method as an alias
alias_method :with, :new
# delegate delivery action to the instance
- def message_arrived(*args)
- new.message_arrived(*args)
+ def message_arrived(*)
+ new.message_arrived(*)
end
end
def initialize(params = {})
@params = params
@@ -489,22 +521,22 @@
# send a pigeon with the message
end
end
class PigeonLine < ActiveDelivery::Lines::Base
- def notify_later(sender, delivery_action, *args, **kwargs)
+ def notify_later(sender, delivery_action, *, **kwargs)
# `to_s` is important for serialization. Unless you might have error
- PigeonLaunchJob.perform_later sender.class.to_s, delivery_action, *args, **kwargs.merge(params: line.params)
+ PigeonLaunchJob.perform_later(sender.class.to_s, delivery_action, *, **kwargs.merge(params: line.params))
end
end
class PigeonLaunchJob < ActiveJob::Base
- def perform(sender, delivery_action, *args, params: nil, **kwargs)
+ def perform(sender, delivery_action, *, params: nil, **)
klass = sender.safe_constantize
handler = params ? klass.with(**params) : klass.new
- handler.public_send(delivery_action, *args, **kwargs)
+ handler.public_send(delivery_action, *, **)
end
end
```
**NOTE**: we fall back to the superclass's sender class if `resolve_class` returns nil.
@@ -589,15 +621,15 @@
end
# We want to broadcast all notifications
def notify?(...) = true
- def notify_now(context, delivery_action, *args, **kwargs)
+ def notify_now(context, delivery_action, *, **)
# Skip if no user provided
return unless context.user
payload = {event: [context.scope, delivery_action].join(".")}
- payload.merge!(serialized_args(*args, **kwargs))
+ payload.merge!(serialized_args(*, **))
DeliveryChannel.broadcast_to context.user, payload
end
# Broadcasts are asynchronous by nature, so we can just use `notify_now`