Railtieを使ってActionMailerのdelivery_methodを拡張してみました。
サンプルで作ったgemはこちら↓

任意のURLにHTTP POSTするdelivery_methodを定義したgemになります。

ということで今回は作り方の備忘として残します。

作り方

Rails::Railtieのサブクラスで定義したinitializerのブロックをRailsが自動で呼び出す仕組みになっています。このinitializerブロック内に拡張する処理を入れていきます。

http_action_mailerの例だと以下のようにActionMailer::BaseがロードされたタイミングでActionMailer::Base#add_delivery_methodでdelivery_methodを追加しています。

delivery_methodに追加するクラスはこんな感じで定義します。基本的にinitializeとdelivery!メソッドを定義すれば良いです。

deliver!の引数にはMail::Messageのオブジェクトが渡されます。コンストラクタの引数にはconfig.xxx_settingsで設定したハッシュが渡されます。xxxの部分にはadd_delivery_methodの第一引数のシンボルの名前が入ります。http_action_mailerの例だとconfig.http_settings = { ... } といった感じで設定できます。xxx_settingsのアクセサはadd_delivery_method呼び出し時に自動的に生成されます。add_delivery_methodの定義はこんな感じです↓

あとはrequire ‘xxx’でRailtieがロードされるように調整します

gem化する場合は、generatorを使ってスケルトン作って、lib直下にRailtieを書けばOK

実際のRailsアプリでテストをしたい場合はtest/dummy配下にRailsアプリが作られているので、コントローラやルーティングを設定してアプリを立ち上げれば、アプリの手動テストができます。

テストコードにrspecを使いたい場合はこちらを参照すると良いです↓

before: ‘action_mailer.set_configs’について

Railtieのinitializerのオプションで before: 'action_mailer.set_configs'を入れないと、config.xxx_settings での設定ができません。set_configsでもActionSupport.on_loadを使ってActionMailer::Baseのロードをフックしていますが、add_delivery_methodをする前にset_configsのhookブロックが呼び出されるとxxx_settingsのメソッドがまだ定義されていないためエラーになります。そのためset_configsの前にadd_delivery_methodを呼び出すブロックをon_loadで渡してあげることで、xxx_settingsのアクセサ定義 → send(“xxx_settings”)呼び出しという流れでdelivery_methodの設定をすることができます。

参考URL