on Rails : login_generatorを本格的に使ってみる2
[Ruby]on Rails : login_generatorを本格的に使ってみる1の続きです.コッチは比較的ソース多めなので,勘弁してください.
モデルのテスト
それでは,先ずはテスト用のtest/fixture/users.ymlを弄ります.ユーザ名を追加したので,ちゃんとfixtureにも追加します.
izumi:
id: 1
name : 泉野明
login: izumi
password: <%= User.sha1("test1") %>
asuma:
id: 2
name : 篠原遊馬
login: asuma
password: <%= User.sha1("test2") %>
isao:
id: 3
name : 太田功
login: isao
password: <%= User.sha1("test3") %>次に,テストケースも弄ります.まずはモデルUserのテストケースから.test/unit/user_test.rbを開き,編集.折角ですから,ユーザ名が入力されていなかったときのテストケースも先に作っちゃいましょう.ひとつだけ,例を載せます.
def test_disallowed_passwords
u = User.new
u.login = "gotou"
u.name = "後藤喜一"
u.password = u.password_confirmation = "tiny"
assert !u.save
assert u.errors.invalid?('password')
u.password = u.password_confirmation = "huge" * 100
assert !u.save
assert u.errors.invalid?('password')
u.password = u.password_confirmation = ""
assert !u.save
assert u.errors.invalid?('password')
u.password = u.password_confirmation = "secure_password"
assert u.save
assert u.errors.empty?
endちゃんとtest_createやtest_bad_password,test_bad_loginにもu.nameを書き,適当に作れたら,モデルだけのテストを行う.
$ rake test:units
さて,test_bad_namesの部分でエラーが出たはずですから,次はモデルの修正をします.
validates_length_of :name, :within => 4 .. 40 # 追加 validates_presence_of :login, :password, :password_confirmation, :name # :nameを追加
こうするだけ.もう一度rake test:unitsをすると,通ります.
全体のテスト
次は普通にrakeを実行してみます.すると,やたらとassert_session_hasで,セッションにuserなんてねーよって怒られるはず.ちなみに,test_auth_bobとかいうのはtest_loginみたいなもんだから,こんなワケの分からん名前は変えましょう.とりあえず,テストケースはこうなりました.
require File.dirname(__FILE__) + '/../test_helper'
require 'account_controller'
# Raise errors beyond the default web-based presentation
class AccountController; def rescue_action(e) raise e end; end
class AccountControllerTest < Test::Unit::TestCase
self.use_instantiated_fixtures = true #忘れずに!
fixtures :users
def setup
@controller = AccountController.new
@request, @response = ActionController::TestRequest.new, ActionController::TestResponse.new
@request.host = "localhost"
end
def test_login
post :login, :user => {:login => "asuma", :password => "test2"}
assert_session_has :user
assert_equal @asuma, @response.session[:user]
assert_redirected_to :action => "welcome"
end
def test_signup
post(:signup,
:user => { :name => "熊耳武緒", :login => "takeo",
:password => "newpassword", :password_confirmation => "newpassword" })
assert_session_has :user
assert_redirected_to :action => "welcome"
end
def test_bad_signup
post :signup, :user => { :name => "新ボブ", :login => "newbob",
:password => "newpassword", :password_confirmation => "wrong" }
assert_invalid_column_on_record "user", "password"
assert_success
post :signup, :user => { :name => "よ", "login" => "yo",
:password => "newpassword", :password_confirmation => "newpassword" }
assert_invalid_column_on_record "user", "login"
assert_success
post :signup, :user => { :name => "よよよ", :login => "yo",
:password => "newpassword", :password_confirmation => "wrong" }
assert_invalid_column_on_record "user", ["login", "password"]
assert_success
end
def test_invalid_login
post :login, :user => {:login => "izumi", :password => "machigai"}
assert_session_has_no :user
end
def test_login_logoff
post :login, :user => {:login => "izumi", :password => "test1"}
assert_session_has :user
get :logout
assert_session_has_no :user
end
endrakeを実行すると,先ず間違いなく失敗すると思います.
ビューを直そう
次に,ビューを弄ります.弄らなければ行けないのは,singupとloginだけ.まずはsignup.rhtmlから.
<%= start_form_tag :action=> "signup" %> <div title="Account signup" id="signupform" class="form"> <h3>サインアップ</h3> <%= error_messages_for 'user' %><br/> <label for="user_name">お名前:</label><br/> <%= text_field "user", "name", :size => 30 %><br /> <label for="user_login">ご希望のログインネーム:</label><br/> <%= text_field "user", "login", :size => 30 %><br/> <label for="user_password">パスワード:</label><br/> <%= password_field "user", "password", :size => 30 %><br/> <label for="user_password_confirmation">パスワード確認:</label><br/> <%= password_field "user", "password_confirmation", :size => 30 %><br/> <%= submit_tag 'サインイン' %> <%= end_form_tag %>
名前入力欄を追加しました.
つぎにlogin.rhtmlを.
<%= start_form_tag :action=> "login" %>
<div title="Account login" id="loginform" class="form">
<h3>ログインしてください</h3>
<% if @message %>
<div id="message"><%= @message %></div>
<% end %>
<p><label for="user_login">ログイン:</label><br/>
<%= text_field 'user', 'login' %></p>
<p><label for="user_password">パスワード:</label><br/>
<%= password_field 'user', 'password' %></p>
<%= submit_tag 'ログイン' %>
<br/>
</div>
<%= end_form_tag %>パラメータを@param[:user][:login]みたいな形にしたかったので,こうしました.こうするとコントローラからも取り易いし,わかり易いし.
コントローラも直そう
最後に,コントローラの編集.
class AccountController < ApplicationController
model :user
layout 'scaffold'
def login
case @request.method
when :post
if @session[:user] = User.authenticate(@params[:user][:login], @params[:user][:password])
flash[:notice] = "Login successful"
redirect_to :action => "welcome"
else
@login = @params[:login]
@message = "Login unsuccessful"
end
end
end
def signup
case @request.method
when :post
@user = User.new(@params[:user])
if @user.save
@session[:user] = User.authenticate(@user.login, @params[:user][:password])
flash[:notice] = "Signup successful"
redirect_to :action => "welcome"
end
when :get
@user = User.new
end
end
def delete
if @params[:id]
@user = User.find(@params[:id])
@user.destroy
end
redirect_to :action => "welcome"
end
def logout
@session[:user] = nil
end
def welcome
end
endいきなりdeleteとか出来てますが,ここは気にしちゃ駄目だと思うぜ.俗に言う親切心ってやつだもんな.
さて,これで出来上がり.rakeをしてみると通ります.
以上で,ごく簡単なlogin_generatorの使い方を終わらせてもらいます.
総括
確かに自動でログイン周りを作ってくれるのは,とても有り難いことだ.しかし,テストケースが始めからできているというのも困った話で,テストケースに関しては,ほとんど一から自分で書くのと変わらないぐらいの労力が必要な気もする.全体を通してみると,楽なのは楽,なのかな?