Skip to content

Commit

Permalink
Add recipients feature for defining recipients inside the notifier (#459
Browse files Browse the repository at this point in the history
)

* Add feature for defining recipients inside the notifier
* Also support blocks
  • Loading branch information
excid3 authored Jun 27, 2024
1 parent 49477ee commit 30e02db
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 0 deletions.
23 changes: 23 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,28 @@
### Unreleased

* Add `recipients` feature to let Notifiers determine their recipients

```ruby
class CommentNotifier < ApplicationNotifier
# Notify all the commenters on this post except the new comment author

# Can be given a lambda or Proc
recipients ->{ params[:comment].post.commenters.excluding(params[:comment].user).distinct }

# Can be given a block
recipients do
params[:comment].post.commenters.excluding(params[:comment].user).distinct
end

# Or can call a method
recipients :fetch_recipients

def fetch_recipients
params[:comment].post.commenters.excluding(params[:comment].user).distinct
end
end
```

### 2.3.3

* Use `public_send` for Email delivery so it doesn't accidentally call private methods.
Expand Down
17 changes: 17 additions & 0 deletions app/models/concerns/noticed/deliverable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ module Deliverable
class_attribute :bulk_delivery_methods, instance_writer: false, default: {}
class_attribute :delivery_methods, instance_writer: false, default: {}
class_attribute :required_param_names, instance_writer: false, default: []
class_attribute :_recipients, instance_writer: false
end

class_methods do
Expand Down Expand Up @@ -39,6 +40,10 @@ def deliver_by(name, options = {})
delivery_methods[name] = DeliverBy.new(name, config)
end

def recipients(option = nil, &block)
self._recipients = block || option
end

def required_params(*names)
required_param_names.concat names
end
Expand Down Expand Up @@ -79,6 +84,8 @@ def deliver(recipients = nil, **options)
# CommentNotifier.deliver(User.all, wait: 5.minutes)
# CommentNotifier.deliver(User.all, wait_until: 1.hour.from_now)
def deliver(recipients = nil, enqueue_job: true, **options)
recipients ||= evaluate_recipients

validate!

transaction do
Expand Down Expand Up @@ -108,6 +115,16 @@ def deliver(recipients = nil, enqueue_job: true, **options)
end
alias_method :deliver_later, :deliver

def evaluate_recipients
return unless _recipients

if _recipients.respond_to?(:call)
instance_exec(&_recipients)
elsif _recipients.is_a?(Symbol) && respond_to?(_recipients)
send(_recipients)
end
end

def recipient_attributes_for(recipient)
{
type: "#{self.class.name}::Notification",
Expand Down
2 changes: 2 additions & 0 deletions test/dummy/app/notifiers/comment_notifier.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
class CommentNotifier < ApplicationNotifier
recipients -> { params[:recipients] }

deliver_by :test

# delivery_by :email, mailer: "UserMailer", method: "new_comment"
Expand Down
34 changes: 34 additions & 0 deletions test/notifier_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,24 @@
class NotifierTest < ActiveSupport::TestCase
include ActiveJob::TestHelper

class RecipientsBlock < Noticed::Event
recipients do
params.fetch(:recipients)
end
end

class RecipientsLambda < Noticed::Event
recipients -> { params.fetch(:recipients) }
end

class RecipientsMethod < Noticed::Event
recipients :recipients

def recipients
params.fetch(:recipients)
end
end

test "includes Rails urls" do
assert_equal "http://localhost:3000/", SimpleNotifier.new.url
end
Expand Down Expand Up @@ -40,6 +58,22 @@ class NotifierTest < ActiveSupport::TestCase
assert_equal ["can't be blank"], notifier.errors[:record]
end

test "recipients block" do
assert_equal [:foo, :bar], RecipientsBlock.with(recipients: [:foo, :bar]).evaluate_recipients
end

test "recipients lambda" do
assert_equal [:foo, :bar], RecipientsLambda.with(recipients: [:foo, :bar]).evaluate_recipients
end

test "recipients" do
assert_equal [:foo, :bar], RecipientsMethod.with(recipients: [:foo, :bar]).evaluate_recipients
end

test "deliver without recipients" do
ReceiptNotifier.deliver
end

test "deliver creates an event" do
assert_difference "Noticed::Event.count" do
ReceiptNotifier.deliver(User.first)
Expand Down

0 comments on commit 30e02db

Please sign in to comment.