WEB + DB PRESS 28号の【特集】Ruby on Rails入門に取り組む(3日目)
今日は出掛けていたので空いた時間に本に書いてあるソースコードを読んで復習をしておいた。
解説を読みながらソースコードを読み解く
今回のポイントをまとめてみた。
- コントローラーに書いたメソッド名がアクションとなり、アクセスされたURLとマッピングされてアクションが呼び出される。
- フィルターでアクションに入る前にコールバック(前処理)を行うことができる。
- 前処理フィルターを外したいアクションは、オプションで指定できる。
- modelはコントローラーの先頭で宣言する
- アクション間で値をやりとり(値の保持)は『flash』という機能で実現できる
- 認証チェックはモデルでメソッド定義を書いた
- Viewではタグを生成されるメソッドが予め用意されている
- エスケープ処理やサニタイジング処理なども用意されている
こんな感じだろうか・・・
一個ずつ紐解いていこう。
コントローラーの動き
class AccountController < ApplicationController #〜略〜 def login #〜略〜 end def logout end def welcome #〜略〜 end def authenticate #〜略〜 end private # フィルター用メソッド def session_authenticate #〜略〜 end end
基本的にフィルター用のメソッド以外で作成した(一部以外はジェネレーターでできた)メソッドがアクションになるようです。
http://localhost:3000/account/login
にアクセスしたら、Accountコントローラーのloginアクションを呼び出すという感じ。
http://localhost:3000/account/welcome
だったら、Accountコントローラーのwelcomeアクション。以下同文。
なるほど。アクションがなければ、
Unknown action No action responded to session_authenticate
と表示されるらしい。(フィルターをコメントアウトしたら確認できた)
フィルターの処理
# アクションを実行する前に呼ぶコールバックを指定する before_filter :session_authenticate , :except => %w(login authenticate)
こんな感じで書けばいいらしい。
session_authenticateというPrivateなメソッドを作って指定する。
気になったのが、フィルター起動を除外するオプションで配列を渡しているんだけど、
[ "login" , "authenticate"] ではなく、 %w()という書き方をしているところ。
なぜだろう??ハッシュのキーがシンボルになっているのは「キーワード」を明示的に表現する為に
使っているのはわかるが、それと同じ利用なのかなぁ??(可視性の理由?)
利用するモデルに関して
利用するモデルは先頭で宣言するらしい。
本の端にコラムで、「RailsとDI」に関して記載されていた。
「アクセサ」でDIという形はあえてとらず、「model」という書き方でクラスローダーという形でダイナミックにモデルを利用できるようにしたらしい。
Userクラスのhogehogeメソッドを使うと見せかけて、テスト環境では「Mockクラス」を呼び出し、実行環境では「実クラス」を呼び出す。
ということができるようになっているらしい。
DIをあえて使わず、「more explicit」な方法を考え出したらしい。
Rubyの特性を活かした機能だって。
>コラムに書いてある事が理解できているか不安なので、「らしい」ばかり書いてします。
DHHすごいなぁ。
こういうところが、Railsと他のフレームワークを比較する際に大事な「【なにができるか】ではなく【どうできるか】」の真骨頂なのでしょうか?
class AccountController < ApplicationController # モデルとしてUserクラスと使うことを宣言する model :user # 〜略〜 end
アクション間での値保持
アクション間のメッセージなどの値保持は『flash』という機能で実現できるみたい。
flashに関してちょっと調べてみた。
『Ruby on Rails入門 優しいRailsの育て方』の187ページに載っていた。
flash機能は特別なセッションの利用方法で、保存時期が次回アクションまでに限定されている。
次のアクション実行時に表示するメッセージを渡す、といった場合に便利。
なるほど、authenticateメソッドで認証エラーしたメッセージを、次のloginのアクションに戻ってきて、ビューで表示する時に利用できるってわけかぁ。
flashには2つメソッドが用意されていて、flashの永続性をコントロールできるらしい。
flash[:errMessage1] = "次のアクションまで有効なメッセージ"
flash[:errMessage2] = "こののアクションまで有効なメッセージ"
flash.keep #どちらも次のアクションまで有効になる
便利だ。
機会を作って、実際に利用してみたい。
認証チェックはモデルでメソッド定義
class User < ActiveRecord::Base # 〜略〜 def self.authenticate(name, password) find_first([ "name = ? and password = ?", name, password ]) end end
本にはサニタイジングの事以外詳しい解説が載っていなくて、なぜselfを書かないといけないのかわからなかった。
舞波本(優しい・・・本の略で使われているみたい)でselfを牽引したところ、
オブジェクト指向的にはメッセージを投げるには、必ずレシーバーが必要になるので、自分自身を表す参照が必要。
それが、"self"。
これが理由なのかなぁ??
findはSQLを実行して、結果のuserオブジェクトを取得するということでしょうか。
findメソッドは「_」で区切って色んな使い方ができるらしい。
find_first()
は1件目のレコードを取得という感じでしょうか。
パラメータにfirstを渡してこんな書き方もできた。
find(:first , :conditions=> [ "name = ? and password = ?", name, password ])
どっちの書き方がお勧めなんだろう…(可視性やメンテナンス性が高いRailsっぽいさとか)
前日、id:secondlifeさんに教えて頂いたRails環境でのconsole確認方法で実行してみた。
ruby server/console >> User.find(:first , :conditions=> [ "name = ? and password = ?", "foouser", "foouser" ]) => #<User:0x484a2fc @attributes={"name"=>"foouser", "id"=>"3", "password"=>"foouser"}> >> User.find(:first , :conditions=> [ "name = ? and password = ?", "foouser", "xxxxxxx" ]) => nil
で実行した結果、あればオブジェクトを返し、なければnilを返すんですね。なるほど。
メソッドの最後の戻り値はreturnがなければ暗黙的に最後の行の結果がかえるので、コントローラーの
条件文で受け取るってわけですね。
# 認証メソッドでログイン認証を行う if user = User.authenticate(@params["me"]["name"], @params["me"]["password"]) # 〜略〜 else # 〜略〜 end
んで、コントローラーでは戻り値を「user」に代入した時の結果をifで条件判断して、処理を切り分けているということかー。
なるほどなるほど。
動作を一個ずつ追うために、こんな例をvimでirbっぽいやつで試してみた。(便利すぎる。これ。)
if user = nil p "success" else p "fail" end
まずはエラー系。
全部選択して出力された結果は
"fail" nil
最後のendでnilを返すってことですね。if文で偽になり結果はelse文を通って、"fail"が出力された。
次は、vimで
user = nil
だけ選択して、「Contorl + enter」を押したところ、結果はnil。つまり if nil の結果は偽ってことですね。
今度は、正常系を試す。
if user = "ok" p "success" else p "fail" end
全選択実行では今度は
"success" nil
表示された。考えていた通りの結果が出てうれしい。「user = "ok"」だけ選択してeval実行の結果は"ok"だから条件文の判定結果は真ってことですね。
Viewでのタグを生成
ERBを使って、書く。
formタグはRailsから提供されているのでそれを使えるらしい。
<h1>Account#login</h1> <p>Find me in app/views/account/login.rhtml</p> <%= form_tag :action => "authenticate" %> name: <%= text_field "me", "name" %><br/> password: <%= password_field "me", "password" %><br/> <%= submit_tag "Login" %> <%= end_form_tag %> <%= h @flash["alert"] %>
仕事ではStrutsでタグライブラリを使って、Viewを書いているので目がなかなか慣れない。
たぶん、rails.vimの機能でViewを便利に書く方法があると思うのですが、surround.vimを拡張した s= で <%= %>をサイドに付加することしか、利用しなかった。(使い方をもっと勉強するぞー)
特にタイポ王なので補完系をもっと覚えたい。
エスケープ処理やサニタイジング処理
これもRailsで用意されているみたい。
SQLで発行した時の、「?」がそれにあたる。使いやすい感じ。>サニタイジング
エスケープも簡単で、hっていうメソッドが用意されていて利用できる。
括弧が省略されているけど、実際は
<%= h(@flash["alert"]) %>
と同じなんですよね。括弧省略すると見やすいなー。
perlを使っている時も、pushなどでは括弧は省略していたので、それほど戸惑いはないなぁ。
これで、第二章完了!