-
-
Notifications
You must be signed in to change notification settings - Fork 30
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Support signature generation for ActionMailer
ActionMailer automatically generates class methods from the instance methods user defined via method_missing. For example, `AccountMailer.welcome_mail` will be generated from `AccountMail#welcome_mail` that is defined by users. This starts to support signature generation for auto-generated class methods for mailer classes dynamically.
- Loading branch information
Showing
12 changed files
with
189 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
module RbsRails | ||
module ActionMailer | ||
def self.class_to_rbs(klass) | ||
Generator.new(klass).generate | ||
end | ||
|
||
class Generator | ||
def initialize(klass) | ||
@klass = klass | ||
@klass_name = Util.module_name(klass, abs: false) | ||
end | ||
|
||
def generate | ||
Util.format_rbs klass_decl | ||
end | ||
|
||
private def klass_decl | ||
<<~RBS | ||
#{header} | ||
#{methods} | ||
#{footer} | ||
RBS | ||
end | ||
|
||
private def header | ||
namespace = +'' | ||
klass_name(abs: false).split('::').map do |mod_name| | ||
namespace += "::#{mod_name}" | ||
mod_object = Object.const_get(namespace) | ||
case mod_object | ||
when Class | ||
# @type var superclass: Class | ||
superclass = _ = mod_object.superclass | ||
superclass_name = Util.module_name(superclass, abs: false) | ||
|
||
"class #{mod_name} < ::#{superclass_name}" | ||
when Module | ||
"module #{mod_name}" | ||
else | ||
raise 'unreachable' | ||
end | ||
end.join("\n") | ||
end | ||
|
||
private def methods | ||
klass.action_methods.map do |method_name| | ||
"def self.#{method_name}: (*untyped) -> ActionMailer::MessageDelivery" | ||
end.join("\n") | ||
end | ||
|
||
private def footer | ||
"end\n" * klass_name(abs: false).split('::').size | ||
end | ||
|
||
private def klass_name(abs: true) | ||
abs ? "::#{@klass_name}" : @klass_name | ||
end | ||
|
||
private | ||
attr_reader :klass | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
module RbsRails | ||
module ActionMailer | ||
def self.class_to_rbs: (untyped klass) -> String | ||
|
||
class Generator | ||
@klass_name: String | ||
|
||
def initialize: (singleton(ActionMailer::Base) klass) -> void | ||
|
||
def generate: () -> String | ||
|
||
def klass_decl: () -> String | ||
|
||
def header: () -> String | ||
|
||
def methods: () -> String | ||
|
||
def footer: () -> String | ||
|
||
def klass_name: (?abs: boolish) -> String | ||
|
||
private | ||
|
||
attr_reader klass: singleton(ActionMailer::Base) | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
class ApplicationMailer < ActionMailer::Base | ||
default from: '[email protected]' | ||
layout 'mailer' | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
class UserMailer < ApplicationMailer | ||
default from: '[email protected]' | ||
|
||
def welcome_email | ||
@user = params[:user] | ||
@url = 'http://example.com/login' | ||
mail(to: @user.email, subject: '私の素敵なサイトへようこそ') | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
<%= yield %> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
class UserMailer < ::ApplicationMailer | ||
def self.welcome_email: (*untyped) -> ActionMailer::MessageDelivery | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
require 'test_helper' | ||
|
||
class ActionMailerTest < Minitest::Test | ||
def test_type_check | ||
clean_test_signatures | ||
|
||
setup! | ||
|
||
dir = app_dir | ||
sh!('steep', 'check', chdir: dir) | ||
end | ||
|
||
def test_user_mailer_rbs_snapshot | ||
clean_test_signatures | ||
|
||
setup! | ||
|
||
rbs_path = app_dir.join('sig/rbs_rails/app/mailers/user_mailer.rbs') | ||
expect_path = expectations_dir / 'user_mailer.rbs' | ||
# Code to re-generate the expectation files | ||
# expect_path.write rbs_path.read | ||
|
||
assert_equal expect_path.read, rbs_path.read | ||
end | ||
|
||
def app_dir | ||
Pathname(__dir__).join('../app') | ||
end | ||
|
||
def expectations_dir | ||
Pathname(__dir__).join('../expectations') | ||
end | ||
|
||
def setup! | ||
dir = app_dir | ||
|
||
Bundler.with_unbundled_env do | ||
sh!('bundle', 'install', chdir: dir) | ||
sh!('bin/rake', 'db:create', 'db:schema:load', chdir: dir) | ||
sh!('bin/rake', 'rbs_rails:all', '--trace', chdir: dir) | ||
end | ||
end | ||
end |