ユーザ管理

今日の作業

ユーザ管理
1)ログイン機能
2)アクセス制御

今日の作業でわかったこと&わからなかったこと

今日でアクセス制御まで終わりそろそろこのアプリも一通り完成に近づいている。
RailsによるアジャイルWebアプリケーション開発のおかげでだいぶRailsについて
理解が深まってきたと実感している。
来週からはテストについて気合いを入れて勉強していく。

来週やること

ユーザ管理のまとめ
仕上げ

調べたことのまとめ

ログイン機能

◎管理者がユーザ名とパスワードを入力するためのフォームの提供
◎ログイン完了した時点から、セッション終了時(ログアウト時)までその管理者がログイン済みであるという情報の保持
◎ログイン済み以外は管理機能を使用できないようにする。
を実現していく。
まずloginコントローラのlogin()アクションを定義。
ログイン済みの情報はsessionに記録する。

  def login
    if request.get?
       session[:user_id] = nil
      @user = User.new
    else
      @user = User.new(params[:user])
       logged_in_user = @user.try_to_login
      if logged_in_user
         session[:user_id] = logged_in_user.id
         redirect_to(:action => "index")
      else
         flash[:notice] = "ユーザ名かパスワードが違います"
      end
    end
  end

このメソッドでは昨日のadd_user()同様、ログイン操作時の最初にGetリクエストが送られてきた時と、
ユーザからフォームデータが返された場合の両方の処理をする。
GETリクエストの場合、セッションデータのユーザ情報をクリアして、
フォームに新しいUserオブジェクトを割り当てる。
POSTデータを受け取った場合、そのデータをparams[:user]で抽出し@userに格納する。
そしてそのオブジェクトのtry_to_login()を呼ぶ。
オブジェクトのユーザ名とハッシュ化されたパスワードがDB内の値と一致した場合に限り
このメソッドはDB内のそのユーザに対応する新しいUserオブジェクトを返す。
user.rbモデルファイルに

  def try_to_login
    User.login(name, password)
  end
  
  def self.login(name, password)
    hashed_password = hash_password(password || "")
    find(:first, :conditions => ["name = ? and hashed_password = ?", name, hashed_password])
  end

find()では:firstパラメータを指定。これは検索オプションと組み合わせることで希望する
1つのオブジェクトを取得できる。
今回:conditionsは「?」を使って置き換えをしている。
条件式を""で囲み、その後カンマ「,」で区切る。
一つ目の?にカンマの後の一番目のnameが二つ目の?にhashed_passwordが入る。

アクセス制御

Railsのフィルタ機能を使う。
フィルタを使用すると、アクションメソッドの呼び出しを捕捉してその呼び出しが実行される
直前や呼び出しから復帰直後、あるいは両方の時点で独自の処理を加えることが可能になる。

クラスメソッド名 実行のタイミング
before_filter アクションメソッド実行の直前
after_filter ビュー描画後
around_filter beforeとafterの両方

今回はbeforeフィルタを使用してadminコントローラ内のアクションすべてと、
loginコントローラ内のloginアクション以外の呼び出しを捕捉する。
フィルタ内ではsession[:user_id]の値の存在の有無を確認する。
このメソッドはコントローラすべての親クラスであるapp/controllers/application.rbファイルに定義する。

  def authorize
    unless session[:user_id]
      flash[:notice] = "ログインしてください"
      redirect_to(:controller => "login", :action => "login")
    end
  end

そしてadminコントローラ、loginコントローラ内に以下の一行を追加する。

class AdminController < ApplicationController
  before_filter :authorize
class LoginController < ApplicationController
  before_filter :authorize, :except => :login

フィルタ適用アクションの指定には

:only => :login loninアクションの呼び出し時だけ認証が必要
:except => :login login以外のアクション呼び出し時認証が必要

この機能は理解しやすかった。