控制器的動作在執行之前、後,若有些共同要執行的動作,可以使用before_filter、after_filter和around_filter來定義,例如若想要檢查使用者是否登入,可以如下:
class ApplicationController < ActionController::Base
before_filter :require_login
def require_login
unless logged_in?
flash[:error] = "Please login to access the page!"
redirect_to new_login_url
end
end
def logged_in?
# 一些判斷使用者是否登入的程式碼,傳回布林值
...
end
end
如上定義之後,任何控制器的動作方法被呼叫之前,都會先呼叫require_login。同理,使用after_filter定義的方法,會在任何動作結束之後呼叫,使用around_filter定義的方法,會在任何動作執行前後呼叫。這三個方法可以搭配:only與:except,例如:
class LoginController < ApplicationController
before_filter :require_login, :except => [:new, :create]
...
end
如上設定,則除了new與create之外,所有的動作之前都會先執行require_login。
與before_filter、after_filter和around_filter相反的是skip_before_filter、skip_after_filter和skip_around_filter,這用於取消曾使用before_filter、after_filter和around_filter定義的過濾器。例如若父類別曾定義過before_filter :require_login:
class LoginController < ApplicationController
skip_before_filter :require_login, :only => [:new, :create]
...
end
如上設定之後,除了new與create被取消之外,其它動作執行之前,都要套用過濾器。
before_filter、after_filter和around_filter定義的過濾器,會依定義順序由上往下執行,如果想依定義相反順序執行,則可以使用prepend_before_filter、prepend_after_filter和prepend_around_filter來定義。
過濾器還可以使用區塊定義,例如:
class ApplicationController < ActionController::Base
before_filter do |controller|
unless controller.send(:logged_in?)
controller.flash[:error] = "You must be logged in"
controller.redirect_to controller.new_login_url
end
end
end
如果你的過濾器是個通用元件,可以用於多個控制器,則可以將過濾器定義為類別:
class LoginFilter
def self.filter(controller)
unless controller.send(:logged_in?)
controller.flash[:error] = "You must be logged in"
controller.redirect_to controller.new_login_url
end
end
end
之後就可以這麼使用:
before_filter LoginFilter
實際上before_filter等可以接受的物件,只要擁有filter實例方法就可以了,所以也可以這麼定義:def filter(controller)
unless controller.send(:logged_in?)
controller.flash[:error] = "You must be logged in"
controller.redirect_to controller.new_login_url
end
end
end