2011年8月27日土曜日

Rails3を初歩から学ぶ #11 セッション管理(RSpec編)

この一連のエントリは
Ruby on Rails 3 Tutorial: Learn Rails by Example (Addison-Wesley Professional Ruby Series)
で参考に学んだことを凝縮してお送りしています。

前回サインインページをつくったので対応するサインイン処理をつくります。
createアクションがそれに該当します。
まずはテストからですが、ここで検証したいのは以下の点です。

「サインインに失敗するケース」
・サインイン画面を再表示すること
・タイトルの検証
・サインインに失敗した旨のメッセージを表示すること

「サインインに成功するケース」
・正しいユーザー名/パウワードでサインインできること
・ユーザー個別のページに遷移すること

ここで問題となるのが「サインインできたかどうか」をどうやって判定するかです。
そのために必要なのは「操作中のユーザーのインスタンス」を参照して、そのインスタンスが「サインイン済みであること」のチェックが出来ることです。
それぞれを可能にするヘルパメソッド「currenjt_user」「signed_in?」が定義されることを想定してテストコードを書いてみましょう。

describe "POST 'create'" do
describe "サインインに失敗するケース" do
before(:each) do
@attr = { :name => "Yam Cha", :password => "invalid" }
end
it "サインイン画面を再表示すること" do
post :create, :session => @attr
response.should render_template('new')
end
it "再表示した画面のタイトル検証" do
post :create, :session => @attr
response.should have_selector("title", :content => "サインイン")
end
it "サインイン失敗した旨を表示する" do
post :create, :session => @attr
flash.now[:error].should =~ /サインインできませんでした/
end
end #サインインに失敗するケース
describe "サインインに成功するケース" do
before(:each) do
@user = Factory(:user)
@attr = { :name => @user.name, :password => @user.password }
end
it "正しいユーザー名/パスワードでサインインできること" do
post :create, :session => @attr
controller.current_user.should == @user
controller.should be_signed_in
end
it "サインインに成功したらユーザー情報ページへ遷移する" do
post :create, :session => @attr
response.should redirect_to(user_path(@user))
end
end #サインインに成功するケース
end # POST 'create'
あまり目新しいものはありませんが1つだけ。
サインイン失敗時のメッセージ表示確認として「flash.now[:error]」を参照しています。
以前登場したときは「flash[:success]」のように直接アクセスしていたのに今回は「now」を経由しています。
なんでしょうか。

これは以前説明した「redirect_to」と「render」の違い、つまりアクションを経由するか否かに関係します。
新規登録時の処理では以下のようになります。

1. Usersコントローラのcreateアクションでflashに値をセットしてredirect_to
2. Usesコントローラのshowアクションを実行
3. Usersビューのshow.html.erbからHTMLを生成(ここでflash表示&クリア)

一方、今回のサインイン失敗時の流れは以下の通りです。

1. Sessionsコントローラのcreateアクションでflashに値をセットしてrender
2. Sessionsビューのnew.html.erbからHTMLを生成(ここでflash表示)

つまり間にアクションを挟みません。flashはアクションを一度またいで値を保持する機能なので、後者のケースでは2終了段階でflashはクリアされていません。
次に何らかのアクションを実行すると再度同じflashが表示されてしまいます。
このような時に「flash.now」をnowを経由することで一度表示した段階でクリアされるよう仕向けることが出来ます。

当然ですが、今の段階でRSpecを実行するとエラーになります。特にcurrent_userやsigned_in?ではNoMethodErrorになりますが、これらは次回からつくっていきましょう。

0 件のコメント:

コメントを投稿