<%= flash[:notice] %>
<% end -%>
<%= @content_for_layout %>
Rails 控制器提供三種過濾器,可在動作執行前/後/環繞插入邏輯:
before_filter:動作前執行,回傳 false 或 render/redirect 可中斷後續流程after_filter:動作後執行around_filter:包裹動作執行(較少用)class ApplicationController < ActionController::Base
def authorize
unless session[:user_id]
flash[:notice] = "Please log in"
redirect_to :controller => "login", :action => "login"
end
end
end
class AdminController < ApplicationController
before_filter :authorize
# 所有動作執行前先檢查登入
def index; end
def list; end
def ship; end
# ...
end
class LoginController < ApplicationController
before_filter :authorize, :except => :login
# login 動作不檢查授權,避免無限迴圈
def login; end
def logout; end
def add_user; end
# ...
end
# login_controller.rb
def list_users
@all_users = User.find(:all)
end
# views/login/list_users.rhtml
<% @page_title = "User List" -%>
<% for user in @all_users -%>
<%= user.name %>
<%= link_to("(delete)", :action => :delete_user, :id => user.id) %>
<% end -%>
# user.rb
before_destroy :dont_destroy_dahuzizyd
def dont_destroy_dahuzizyd
raise "Can't destroy dahuzizyd" if self.name == 'dahuzizyd'
end
# login_controller.rb
def delete_user
id = params[:id]
if id && user = User.find(id)
begin
user.destroy
flash[:notice] = "User #{user.name} deleted"
rescue
flash[:notice] = "Can't delete that user"
end
end
redirect_to :action => :list_users
end
模型回呼 before_destroy 拋出例外,控制器捕獲並轉為友善提示。
# views/layouts/admin.rhtml
ADMINISTER Pragprog Books Online Store
<%= stylesheet_link_tag "scaffold", "depot", "admin", :media => "all" %>
<% if session[:user_id] -%>
<%= link_to("Products", :controller => "admin", :action => "list") %>
<%= link_to("Shipping", :controller => "admin", :action => "ship") %>
<%= link_to("Add user", :controller => "login", :action => "add_user") %>
<%= link_to("List users", :controller => "login", :action => "list_users") %>
<%= link_to("Log out", :controller => "login", :action => "logout") %>
<% end -%>
<% if flash[:notice] -%>
<%= flash[:notice] %>
<% end -%>
<%= @content_for_layout %>
def logout
session[:user_id] = nil
flash[:notice] = "Logged out"
redirect_to :action => "login"
end
# store_controller.rb
before_filter :find_cart, :except => :index
def find_cart
@cart = (session[:cart] ||= Cart.new)
end
# 移除各動作中重複的 @cart = find_cart
使用 before_filter 集中處理共同前置邏輯,乾淨符合 DRY 原則。