diff --git a/CHANGELOG.md b/CHANGELOG.md index 5389870..5269c54 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ - View helpers inside presenter context. - View helpers for presenters within views. - View helpers for presenters within controllers. +- View helpers for presenters within mailers. ## [0.3.0] — 2024-10-27 diff --git a/README.md b/README.md index 6622b25..712c4f7 100644 --- a/README.md +++ b/README.md @@ -156,7 +156,8 @@ end View context is set automagically to enable helpers: - in views, -- in controller actions. +- in controller actions, +- in mailer actions. ## Development diff --git a/config/initializers/action_controller.rb b/config/initializers/action_controller.rb index 5544b90..2929719 100644 --- a/config/initializers/action_controller.rb +++ b/config/initializers/action_controller.rb @@ -11,3 +11,4 @@ def set_presenter_context(&) end ActiveSupport.on_load :action_controller, &presenter_context +ActiveSupport.on_load :action_mailer, &presenter_context diff --git a/spec/internal/app/mailers/application_mailer.rb b/spec/internal/app/mailers/application_mailer.rb new file mode 100644 index 0000000..2dfcdd5 --- /dev/null +++ b/spec/internal/app/mailers/application_mailer.rb @@ -0,0 +1,6 @@ +# frozen_string_literal: true + +class ApplicationMailer < ActionMailer::Base + default from: 'from@example.com' + layout 'mailer' +end diff --git a/spec/internal/app/mailers/person_mailer.rb b/spec/internal/app/mailers/person_mailer.rb new file mode 100644 index 0000000..e19ed64 --- /dev/null +++ b/spec/internal/app/mailers/person_mailer.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +class PersonMailer < ApplicationMailer + def welcome + @person = params[:person].decorated + @family = @person.children + @url = @person.url + @urls = @person.class.urls + + mail subject: "#{@person.name} joined us" + end +end diff --git a/spec/internal/app/models/person.rb b/spec/internal/app/models/person.rb index 1702692..a23a9ad 100644 --- a/spec/internal/app/models/person.rb +++ b/spec/internal/app/models/person.rb @@ -1,5 +1,6 @@ # frozen_string_literal: true class Person < ApplicationRecord - belongs_to :parent, class_name: 'Person' + belongs_to :parent, class_name: 'Person', inverse_of: :children + has_many :children, class_name: 'Person', inverse_of: :parent end diff --git a/spec/internal/app/presenters/person_presenter.rb b/spec/internal/app/presenters/person_presenter.rb index 4dd12ec..a338cf4 100644 --- a/spec/internal/app/presenters/person_presenter.rb +++ b/spec/internal/app/presenters/person_presenter.rb @@ -7,6 +7,12 @@ def links link_to('All', model_class), ] end + + def urls + { + all: url_for(model_class), + } + end end def name = "#{first_name} #{last_name}" diff --git a/spec/internal/app/views/layouts/mailer.html.erb b/spec/internal/app/views/layouts/mailer.html.erb new file mode 100644 index 0000000..63fd42c --- /dev/null +++ b/spec/internal/app/views/layouts/mailer.html.erb @@ -0,0 +1,19 @@ + + + + + + + + + <%= yield %> + + + + diff --git a/spec/internal/app/views/layouts/mailer.text.erb b/spec/internal/app/views/layouts/mailer.text.erb new file mode 100644 index 0000000..37f0bdd --- /dev/null +++ b/spec/internal/app/views/layouts/mailer.text.erb @@ -0,0 +1 @@ +<%= yield %> diff --git a/spec/internal/app/views/person_mailer/welcome.html.erb b/spec/internal/app/views/person_mailer/welcome.html.erb new file mode 100644 index 0000000..1c6415f --- /dev/null +++ b/spec/internal/app/views/person_mailer/welcome.html.erb @@ -0,0 +1,21 @@ +<% content_for :links do %> + +<% end %> + +

Welcome <%= @person.link %>!

+ +<% if @family %> +

Family

+ + +<% end %> diff --git a/spec/internal/app/views/person_mailer/welcome.text.erb b/spec/internal/app/views/person_mailer/welcome.text.erb new file mode 100644 index 0000000..11d48f7 --- /dev/null +++ b/spec/internal/app/views/person_mailer/welcome.text.erb @@ -0,0 +1,12 @@ +Welcome <%= @person.name %>! + +<% if @family %>Family: +<% for person in @family do %> +* <%= person.name %><% end %> +<% end %> + +Details: <%= @url %> + +<% for name, url in @urls do %>See also: +* <%= name.to_s.humanize %>: <%= url %> +<% end %> diff --git a/spec/internal/config/environment.rb b/spec/internal/config/environment.rb index ef8a697..1030d31 100644 --- a/spec/internal/config/environment.rb +++ b/spec/internal/config/environment.rb @@ -7,6 +7,7 @@ Combustion.initialize! *%i[ active_record action_controller + action_mailer active_job ], **{ database_reset: false, diff --git a/spec/mailers/person_mailer_spec.rb b/spec/mailers/person_mailer_spec.rb new file mode 100644 index 0000000..2d954c4 --- /dev/null +++ b/spec/mailers/person_mailer_spec.rb @@ -0,0 +1,52 @@ +# frozen_string_literal: true + +RSpec.describe PersonMailer do + subject { described_class.with person: john } + + let(:john) { Person.create! first_name: 'John', last_name: 'Smith' } + let(:mathew) { Person.create! first_name: 'Mathew', last_name: 'Johnson', parent: john } + + describe 'welcome' do + subject { super().welcome } + + before { mathew } # should exist + + it { is_expected.to have_attributes subject: 'John Smith joined us' } + + describe 'HTML' do + include RSpecHtmlMatchers + + subject { super().html_part.body.to_s } + + it { is_expected.to have_tag 'h1', text: 'John Smith' } + it { is_expected.to have_tag 'li .name', text: 'Mathew Johnson' } + + describe 'helpers within a view' do + describe 'instance-level' do + it { is_expected.to have_tag 'a', href: url_for(mathew), text: 'Mathew Johnson' } + end + + describe 'class-level' do + it { is_expected.to have_tag 'nav a', href: people_path, text: 'All' } + end + end + end + + describe 'text' do + subject { super().text_part.body.to_s } + + it { is_expected.to include 'Welcome John Smith!' } + it { is_expected.to include '* Mathew Johnson' } + + describe 'helpers within a mailer action' do + describe 'instance-level' do + it { is_expected.to include "Details: #{url_for john}" } + end + + describe 'class-level' do + it { is_expected.to include "* All: #{people_url}" } + end + end + end + end +end