上篇的啟發,這篇是實作的部份,只講概念,因為實際的code與系統架構差異甚大,所以請自行設計內容物
大概是這樣的,先在model內增加like
複製內容到剪貼板
代碼:
class User < ActiveRecord::Base
def is_admin? ; end
def is_editor? ; end
end
class Organization < ActiveRecord::Base
def is_admin?(user) ; end
def is_editor?(user) ; end
def is_member?(user) ; end
end因為這個check很常用,所以直接上application controller(各只寫一個當demo|||)
複製內容到剪貼板
代碼:
class ApplicationController < ActionController::Base
def site_editor_check
unless logged_in? && current_user.is_editor?
warning_stickie("您進入到了全站編輯者專用的區域,但您並未擁有編輯者的身分,已儲存IP位址相關資訊,君子請自重")
redirect_back_or_default('/')
return false
end
return true
end
def org_admin_check
unless logged_in? && @organization && @organization.is_admin?(current_user)
warning_stickie("您進入到了公司管理員專用的區域,但您並未擁有管理員的身分,已儲存IP位址相關資訊,君子請自重")
redirect_back_or_default('/')
return false
end
return true
end
end裡面有個重點在於@organization的產生,如果都是使用paramd[:id] or params[:org]之類的方式來指定,可以獨立寫出一個action來做filter,來產生@organization即可(或是你高興也可以在check內直接判定),當然不是凡事都那麼美好,所以就會有兩種指定check的方式
複製內容到剪貼板
代碼:
class UsersController < ActionController::Base
before_filter :site_admin_check
before_filter :org_admin_check, :only => [ :edit, :update ]
skip_before_filter :site_member_check
end最後一個skip是用在如果已經繼承之後的情況下,例如application controller有before_filter,但繼承的users controller又不想用那個filter時使用,而only是用在指定action的情況下,或是用except來做排除指定的action,這是全域的宣告,而如果想用在action內,也就是前述所提的@organization產生後的情況,請在action內指定為
複製內容到剪貼板
代碼:
class UsersController < ActionController::Base
def index #需Org最高權限管理員身分
@organization = Organization.first
return unless org_admin_check
....
end
end要用return中斷的原因在於任何一個action內只能有一個render或redirect_to,而filter算是預先執行的action,和本身的action分離,但在action內呼叫的話就算是同一個action,所以需要return來做brake的動作,&系統做大後,也建議在每個action後面加註解,包括所需要的身分與用途之類的,不然才不會看到眼花X"D
以上的code尚未測試,but照理可行,實作後有錯誤再另補上,以上