diff --git a/docs/delivery_methods/email.md b/docs/delivery_methods/email.md index 5237e134..93d94d18 100644 --- a/docs/delivery_methods/email.md +++ b/docs/delivery_methods/email.md @@ -15,6 +15,21 @@ deliver_by :email do |config| end ``` +Mailer methods with keyword arguments are also supported. + +```ruby +deliver_by :email do |config| + config.mailer = "UserMailer" + config.method = :greeting + config.params = ->{ params } + config.kwargs = ->{ {body: "Hey there", subject: "Thanks for joining"} } + + # Enqueues a separate job for sending the email using deliver_later. + # Deliveries already happen in jobs so this is typically unnecessary. + # config.enqueue = false +end +``` + ##### Options - `mailer` - **Required** @@ -30,6 +45,12 @@ end Use a custom method to define the params sent to the mailer. `recipient` will be merged into the params. - `args` - _Optional_ + + The arguments for the `method` if it uses **positional arguments** (eg: `def hello(a, b, c=1)`) + +- `kwargs` - _Optional_ + + The arguments for the `method` if it uses **keyword arguments** (eg: `def hello(a:, b:, c: 1)`) - `enqueue: false` - _Optional_ diff --git a/lib/noticed/delivery_methods/email.rb b/lib/noticed/delivery_methods/email.rb index e53d997a..7dcf8b9b 100644 --- a/lib/noticed/delivery_methods/email.rb +++ b/lib/noticed/delivery_methods/email.rb @@ -7,7 +7,20 @@ def deliver mailer = fetch_constant(:mailer) email = evaluate_option(:method) args = evaluate_option(:args) || [] - mail = mailer.with(params).public_send(email, *args) + kwargs = evaluate_option(:kwargs) || {} + + if args.present? && kwargs.present? + raise ArgumentError, "`args` and `kwargs` cannot both be provided." + end + + mailer_instance = mailer.with(params) + + mail = if kwargs.present? + mailer_instance.public_send(email, **kwargs) + else + mailer_instance.public_send(email, *args) + end + (!!evaluate_option(:enqueue)) ? mail.deliver_later : mail.deliver_now end diff --git a/test/delivery_methods/email_test.rb b/test/delivery_methods/email_test.rb index 20915759..0bb70f9f 100644 --- a/test/delivery_methods/email_test.rb +++ b/test/delivery_methods/email_test.rb @@ -8,7 +8,7 @@ class EmailTest < ActiveSupport::TestCase @notification = noticed_notifications(:one) end - test "sends email" do + test "sends email (with args)" do set_config( mailer: "UserMailer", method: "new_comment", @@ -21,6 +21,78 @@ class EmailTest < ActiveSupport::TestCase end end + test "sends email (with kwargs)" do + set_config( + mailer: "UserMailer", + method: "greeting", + params: -> { {foo: :bar} }, + kwargs: -> { {body: "Custom"} } + ) + + assert_emails(1) do + @delivery_method.deliver + end + end + + test "sends email (with kwargs, replacing default argument)" do + set_config( + mailer: "UserMailer", + method: "greeting", + params: -> { {foo: :bar} }, + kwargs: -> { {body: "Custom", subject: "Testing"} } + ) + + assert_emails(1) do + @delivery_method.deliver + end + end + + test "raises the underlying ArgumentError if kwargs are missing" do + set_config( + mailer: "UserMailer", + method: "greeting", + params: -> { {foo: :bar} }, + kwargs: -> { {baz: 123} } + ) + + error = assert_raises ArgumentError do + @delivery_method.deliver + end + + assert_equal "missing keyword: :body", error.message + end + + test "raises the underlying ArgumentError if unknown kwargs are given" do + set_config( + mailer: "UserMailer", + method: "greeting", + params: -> { {foo: :bar} }, + kwargs: -> { {body: "Test", baz: 123} } + ) + + error = assert_raises ArgumentError do + @delivery_method.deliver + end + + assert_equal "unknown keyword: :baz", error.message + end + + test "raises an ArgumentError if both args and kwargs are present, since only one can be used" do + set_config( + mailer: "UserMailer", + method: "greeting", + params: -> { {foo: :bar} }, + args: -> { ["hey"] }, + kwargs: -> { {body: "Test"} } + ) + + error = assert_raises ArgumentError do + @delivery_method.deliver + end + + assert_equal "`args` and `kwargs` cannot both be provided.", error.message + end + test "enqueues email" do set_config( mailer: "UserMailer", diff --git a/test/dummy/app/mailers/user_mailer.rb b/test/dummy/app/mailers/user_mailer.rb index ba07b19e..10f57165 100644 --- a/test/dummy/app/mailers/user_mailer.rb +++ b/test/dummy/app/mailers/user_mailer.rb @@ -3,6 +3,10 @@ def new_comment(*args) mail(body: "new comment") end + def greeting(body:, subject: "Hello") + mail(body: body, subject: subject) + end + def receipt mail(body: "receipt") end