コメント投入で notify メイル送信

多分新しいバージョンだと実装済みなんだろな。とりあえず勉強とゆー事で。

  • クラス名は CommentMailer とかにしちゃえ
  • script/generate で試験のカタは作ってくれるハズ
  • AWDwR にサンプル記述あり

てコトでいきなり作ってみよう。

$ ruby script/generate mailer CommentMailer input
      exists  app/models/
      create  app/views/comment_mailer
      exists  test/unit/
      create  test/fixtures/comment_mailer
      create  app/models/comment_mailer.rb
      create  test/unit/comment_mailer_test.rb
      create  app/views/comment_mailer/input.rhtml
      create  test/fixtures/comment_mailer/input
$

とりあえず、コメント投入時に投稿者に notify が送信されれば良いとみて、メソドはひとつだけ、としてみる。試験も一緒に作成されていますな。test/fixtures にディレクトリを掘ってメソド名のファイルが作成されております。

test/fixtures/comment_mailer/input

CommentMailer#input

Find me in app/views/comment_mailer/input.rhtml

なんだこれは、と思いつつスルー。(こら
# よく見てみると app/views/comment_mailer/input.rhtml と中身が一緒

あ、しまった。くまくま本に ActionMailer は日本語がナニ、って出てたぞ。だから今日机の上に AWDwR と一緒にくまくま本を置いてたんだった (家にくまくま本を置いてきた)。とりあえず英語で notify だけ入れる形を取ろう (こらー

とほほな追記

ここまでヤッた時点で、config/environments/ なナニをチェキ入れてみた。なんか微妙。あまりの微妙さ加減に本番環境なソレを見てみると config/environments/production.rb 方面にメイル関連の記述ナシ。おいおい馬鹿かおまえは (誰

しかも本番環境で config/environments/development.rb なんて conflict しちゃってるしー (駄目)。なんつーか、この微妙なオペレーションって何とかならんのか。(って自分に文句言っても仕方ない)

とりあえずの方針として、config 配下は本番な環境下でいろいろいぢる、というナニだったのが元凶だろうな。どうせ環境としては一つしかない (本当か??) のでリポジトリに反映させた方が良いのだろうか。このあたりの know-how が全く無いので体当りするしかない部分がとても嫌です。
一応上記の方針にて config/environments/production.rb を修正。

ActionMailer な作業に戻る

google 先生にお伺いをタテた所、くまくま本の中の人中心 (?) に実装例がてんこ盛り。一緒に盛り込んでしまう方向で検討してみる事に。とりあえずActionMailer 日本語化プラグインを参考に、とゆー事で。

  • config/environments/ 配下のナニな方々の修正
  • plugin の作成
  • test/units/ 配下のアレの実装
  • app/models/ 配下のソレの実装と unit test
  • テンプレートの作成
  • 機能試験の追加
  • コントローラにおけるナニの実装と functional test
  • メイル配送な確認

参考サイトでは、plugin として実装との事にて script/plugin なナニでやれば良いのでしょうが、手でやる。書いてある通りに二つのファイルを作成してコピペ。実装する前に試験を書かねば、なのですが AWDwR によると create_* を使ってナカミをチェキしてるだけで OK な模様。作成された fixture に関する記述もあるので今から読む。

ActionMailer な unit test について

なんか、script/generate mailer した時点で作成されたナニは試験に通るようなものが生成されている様子。関係するファイル達を以下に。

app/models/comment_mailer.rb

class CommentMailer < ActionMailer::Base

  def input(sent_at = Time.now)
    @subject    = 'CommentMailer#input'
    @body       = {}
    @recipients = ''
    @from       = ''
    @sent_on    = sent_at
    @headers    = {}
  end
end

test/unit/comment_mailer_test.rb

require File.dirname(__FILE__) + '/../test_helper'
require 'comment_mailer'

class CommentMailerTest < Test::Unit::TestCase
  FIXTURES_PATH = File.dirname(__FILE__) + '/../fixtures'
  CHARSET = "utf-8"

  include ActionMailer::Quoting

  def setup
    ActionMailer::Base.delivery_method = :test
    ActionMailer::Base.perform_deliveries = true
    ActionMailer::Base.deliveries = []

    @expected = TMail::Mail.new
    @expected.set_content_type "text", "plain", { "charset" => CHARSET }
  end

  def test_input
    @expected.subject = 'CommentMailer#input'
    @expected.body    = read_fixture('input')
    @expected.date    = Time.now

    assert_equal @expected.encoded, CommentMailer.create_input(@expected.date).encoded
  end

  private
    def read_fixture(action)
      IO.readlines("#{FIXTURES_PATH}/comment_mailer/#{action}")
    end

    def encode(subject)
      quoted_printable(subject, CHARSET)
    end
end

test/fixtures/comment_mailer/input

CommentMailer#input

Find me in app/views/comment_mailer/input.rhtml

app/views/comment_mailer/input.rhtml

CommentMailer#input

Find me in app/views/comment_mailer/input.rhtml

これは又サービス満点な事で (絶句
多分今の時点で rake test:units したら試験は通るな。(ヤッてみたら本当に通った。当たり前と言えば当たり前か)

しかしこれは困った。Iso2022JpMailer との整合性とゆーかナニが微妙やっさ。

試験の修正

うーむ。微妙。とりあえず二点の問題があるものと。

  • charset が utf-8 に。これは単純に iso-2022-jp にすれば OK??
  • @expected が TMail::Mail のインスタンスになっている。

短気なので CHARSET だけ修正して plugin と model を実装してみます。えーと、app/controller/article_controller.rb の comment メソドによれば

if @request.post? and @comment.save

が真ならコメント投入 OK ってコトなんでこのあたりに deliver_input の呼び出しが入るとして、渡す必要があるのは @comment だけで OK か。
んで input で必要な情報は、というと

  • @comment.body
  • User.find(Article.find(@comment.article_id).user_id).email

か。なんかメルアドの取り出し方が微妙なんですが、なんとかなるハズ。(今はスルー)

とりあえずの実装がこんな感じ。(文字コードUTF-8)
app/models/comment_mailer.rb

class CommentMailer < ActionMailer::Base

  def input(comment, sent_at = Time.now)
    @subject    = 'コメント投稿通知'
    @body       = { :comment => comment.body, 
      :title => Article.find(comment.article_id).title, 
      :posted_by => comment.created_at, 
      :email => comment.email, 
      :url => comment.url, 
      :ip => comment.ip }
    @recipients = "#{User.find(Article.find(comment.article_id).user_id).email}"
    @from       = ''
    @sent_on    = sent_at
    @headers    = {}
  end
end

notify メイルなテンプレは livedoor を真似てみた。以下のような感じ。
app/views/comment_mailer/input.rhtml (文字コードUTF-8)

「<%= @title %>」にコメントがありました。

Posted by : <%= @posted_by %>
email : <%= @email %>
URL : <%= @url %>
IP : <%= @ip %>

<%= @comment %>

※このメールには返信できませんのでご注意下さい。

一応試験も修正したんで rake test:units してみる。

当たり前だけど駄目だった。

ちょっと一服してきます。orz

試験 NG

試験な出力を見るに、@expected は

なのが NG な原因な模様。無理矢理やっちゃうしかないのかな??

むむ

作業再開し、いろいろ無理矢理ヤッてみたのですが、素直に ActiveHeart を入れた方が良い、という結論に達しました。ちなみに上記についてですが JIS encode されていないのは CommentMailer なナニに見えます。
script/console にて IO.readlines("test/fixtures/comment_mailer/input") な文字列と CommentMailer.create_input(引数略).body が全く同じなんスよねぇ。げ、よく見りゃ Posted by な日付の文字列も違うぢゃん(駄目

今日の敗因はくまくま本を忘れた事、なのだろーか。そうではないと信じたい。(そうでなかった場合、何が敗因かについては略