Rails2.3アプリをRails3.2にアップグレードする、その3

少し間が開きましたが、今回はメール、Cucumber、Javascriptまわりです

メール送信

ActionMailer

メールは Rails3で ActionMailerで仕様が以下のように少し変わりました。またActionMailerを継承したクラスは app/mailers に置くようになりました。

仕様の変更は機械的に変更できるものばかりですね。

class CustomerMail < ActionMailer::Base
  helper :application
  
  # パスワード再設定用メールの送信
  def password_reset(to_addr, url, timeout, name)
    subject    "パスワードの再設定"
    recipients to_addr
    from       FROM_ADDRESS
    body       :url=>url, :timeout=>timeout, :name=>name
  end

  ・・・
class CustomerMail < ActionMailer::Base
  helper :Application
  
  # パスワード再設定用メールの送信
  def password_reset(to_addr, url, timeout, name)
    @url = url
    @timeout = timeout
    @name = name
    mail(
      :subject  =>  "パスワードの再設定",
      :to => to_addr,
      :from => FROM_ADDRESS)
  end

  ・・・
テンプレート (view)

メールのテンプレート (view)はほぼそのまま使えます。ただし < & > 等がエスケープされますので、raw を追加する必要がある部分もあるかもしれません。

日本語

あいかわらず、日本語メールが送れません ^^);
mail-iso-2022-jp という gem をインストールすると ISO-2022-JP のメールが送信できます。 ただし、この場合は UTF-8からJISコードに変換出来ない文字でエラーが発生するので、何らかの対応を考えておく必要があります。

最近はPCはもちろん、携帯でもUTF-8のメールを受信出来るようなので、UTF-8で送信すれば上の文字コードの問題は発生しません(一部のメーラー、携帯では文字化けするかも知れませんが・・・)。
私が Rails3.0以降に作ったシステムでは UTF-8で送信していますが、今のところ問題は無いようなので、今回もUTF-8で送信する事にしました。
Rails3で送信するメールの本文をbase64ではなく8bitにする方法 - 思っているよりもずっとずっと人生は短い。 を参考に、 Mail::Message deliver_jp メソッドを追加して使っています(もちろん deliverを置き換えても良いのですが・・・)。

module Mail
  class Message
    def deliver_jp
      self.tap {|m| m.transport_encoding = '8bit'}.deliver
    end
  end
end

Cucumber

このアプリでは受け入れ(統合?)テストを Cucumber で書きました。 その時点ではCucumber 0.8.3 で Webrat を使っていました。 今回は Cucumber 1.1.9 + Capybara-webkit です。

設定や基本的なstep ファイル

設定や web_steps.rb 、 web_steps_ja.rb は空のRailsプロジェクトにCucumberをインストールして出来た物をベースに必要な部分のみ Rails2.3からコピーしました。

step の中で 他のステップを利用する場合は step と書くように変わったんですね

  • Cucumber 0.8.3
When /^"([^\"]*)"ボタンをクリックする$/ do |button|
  When %Q(I press "#{button}")
end
  • Cucumber 1.1.9
もし /^"([^"]*)"ボタンをクリックする$/ do |button|
  step %{I press "#{button}"}
end
シナリオ(フィーチャー)

Cucumberが正常に動くようにるにのに手間がかかりましたが、ほとんどのシナリオはそのまま通りました。

問題があったのは

  • 画像をボタンのように使っている場合
<a href="action"><img src="a_button.png" title="Aボタン"/></a> 

上のHTMLは もし "Aボタン"リンクをクリックする と書けたのですが、Captbaraは画像のtitleを見てくれません。ここは仕方なく もし "a_button"リンクをクリックする と変更しました。(a タグにtitleを付けたりしたのですがダメでした・・・・)

  • エラーメッセージ

Rails2.3ではvalidationのエラーメッセージは 名前 を入力して下さい のように入力項目とエラーメッセージの間にスペースがあったのですがRails3.2では無くなっていましたので修正しました。

  • visit のオプション引数

Webrat では visitのオプション引数でパラメターやメソッド(POST,PUT...)を指定できたので Javascript でリンクからPUTを送る部分は、これを使ってテストしていましたがCapybaraではvisitのオプション引数はありませんでした。
しかし、今回はJavascriptが動作するCapybara-webkit なので step はリンクのクリックを書くだけで正しくテストが行えました。素晴らしい!

Javascript関連

  • :method => :delete のリンク

: method => :delete のリンクが正しく動作しませんでした。 じつはRails2.3の時点で jquery を使っていたので jquery.js ファイルもそのまま使っていましたが、バージョンが1.3.2 と古く、これが原因でした! Rails3.2の jquery.js を使うようにしたら動きました。

  • :method => :delete のリンクをクリックすると Can't verify CSRF token authenticity が発生

ログアウトリンクをクリックすると、セッションが消えてしまう(新しくなってしまう)という不思議な現象が発生していました。ログを良くみると WARNING: Can't verify CSRF token authenticity と出ていいます。たしかに authenticity_tokenが来ていません・・・・・ ここで、Rails3のlayoutテンプレートのの最後に <%= csrf_meta_tags %> が在ることを以前から不思議に感じていた事を思い出し、layoutテンプレートに加えたところ、正しく動作するようになりました ^^)/


Rails2.3からRails3.2へのポーティングはかなり完成に近づいて来ました。