こんにちは、鈴木です。
Rails に限った話ではありませんが、プロジェクトが大きくなるに従い「○○するときは必ず○○する」というルールは増えていきます。
良いルールは規律をもたらしますが、そうでもないルールはあまりメリットもなく、数が増えてくると「守らなければいけない」という重圧だけが残ります。
「必ず○○する」というルール
以下のコードを見てください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
# # システム運用者に送信するメールを構築する. # # ※メールの Subject は build_subject メソッドを通して構築してください. # class SystemMailer < ActionMailer::Base # 通知メール. def notice(subject, message) # View で使います. @message = message :subject => build_subject("[NOTICE] #{subject}") # 必ず build_subject を呼ぶ. end # エラーメール. def error(subject, message) # View で使います. @message = message :subject => build_subject("[ERROR] #{subject}") # 必ず build_subject を呼ぶ. end protected # メールの Subject を構築する. # 与えられた文字列に Rails.env とサーバ名を付加した文字列を生成する. # Ex. build_subject('[NOTICE] バッチ処理完了') # => '[production][example.com][NOTICE] バッチ処理完了' def build_subject(subject) "[#{Rails.env}][#{Socket.gethostname}]#{subject}" end end |
これは Rails プロジェクトでシステム運用者に対する通知メールを構築するクラスを想定して書いたコードです。
notice と error はそれぞれ、通知メール、エラーメールを構築するメソッドです。
注目していただきたいのは、「# 必ず build_subject を呼ぶ.」と「# ※メールの Subject は build_subject メソッドを通して構築してください.」というコメントです。
メールの Subject は必ず build_subject を通して構築するルールです。
build_subject を見ると、渡された文字列に Rails.env とシステムが動作するホスト名を付加しています。
- メールの Subject に Rails.env とホスト名が含まれると便利だ。
- Rails.env とホスト名を付加する処理を build_subject メソッドに抽出した。
- メールの Subject は必ず build_subject を通して構築するというルールが生まれた。
という経緯で、このようなことになりました。
ルールを仕組みに置き換える
「必ず build_subject を呼ぶ」というルールは妥当でしょうか。規律をもたらす良いルールでしょうか。
必ずやらなければならないことがあるなら、自動的にやっておいてくれる仕組みがあった方が幸せになれます。
ということで、以下のように書き換えてみました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
class SystemMailer < ActionMailer::Base # 通知メール. def notice(subject, message) # View で使います. @message = message :subject => "[NOTICE] #{subject}" end # エラーメール. def error(message) # View で使います. @message = message :subject => "[ERROR] #{subject}" end protected # Subject に Rails.env とホスト名を付加する. def mail_with_subject_prefix(headers={}, &block) mail = mail_without_subject_prefix(headers, &block) mail.subject = "[#{Rails.env}][#{Socket.gethostname}]#{mail.subject}" mail end alias_method_chain :mail, :subject_prefix end |
mail_with_subject_prefix というメソッドを作成し、alias_method_chain でオリジナルの mail メソッドを置き換えました。
「必ず build_subject を呼び出す」というルールを「Subject には自動的に Rails.env とホスト名が付加される」という仕組みに変えることが出来ました。
いつでも上手くいくとは限りませんが、ルールを仕組みに置き換えるメリットは非常に大きいです。
何かを実現する方法が複数あるときは、「ルールより仕組みを作る」という観点で考えてみてはどうでしょう。