--- title: 12th 鐵人賽 Day_20 pundit ? tags: 12th 鐵人賽 --- # 12th 鐵人賽 Day_20 pundit ? 嗨!各位朋友大家好,打給後,歹嘎吼,胎尬喉,我是阿圓,一樣有請今天的one piece:  (雷利大叔!!) 鐵人賽的進度來到三分之二了呢!今天想跟各位來介紹 pundit 這個平常在專案裡面,使用程度很高的gem! ## 權限管理系統(pundit) 若今天的專案比較複雜一點,你可能會需要定義一下 user 權限,除了在controller裡寫下一大堆`if...else`判斷外,你有另一個選項是使用pundit 這個 gem。 pundit 會在資料夾中生成與 controller 同名的 policy,而你可以在 policy 去定義跟與各個 action 有關的權限。 ### 基本安裝 首先無例外的記得先到 gemfile : `gem "pundit"` (記得bundle) 接著,到 application controller的檔案裡面引入: ```ruby= class ApplicationController < ActionController::Base include Pundit end ``` 最後,記得執行pundit的安裝: `rails g pundit:install` 這樣,就會長出`app/policies/`的這個資料夾,設定好後,就可以在controller、view 裡使用了! `rails g pundit:policy post` 就會幫你建立 post 的 policy 了! ### 使用方法 policy 設定方法呢,就是定義檢查登入者(user) 有沒有辦法對資料(record) 進行某種操作 (update?),而一般來說,policy 遵從以下幾點: 1. policy 裡的類別命名,都是 modle 名稱後面接 Policy 2. policy 接收兩個參數,第一個是 user ,而預設會呼叫 `current_user` 這個方法,若沒有使用 devise 這個 gem ,請記得作一個給他! 3. 第二個參數是想要驗證能否執行操作的 model(ex:post) 4. policy 裡的方法名,一般都是使用 action 的名稱後面加個問號(ex:update?) ```ruby= class PostPolicy attr_reader :user, :post def initialize(user, post) @user = user @post = post end def update? user.admin? or not post.published? end end ``` 以上方的例子,我們可以在 post_controller 裡使用`authorize`這個方法: ```ruby= def update @post = Post.find(params[:id]) authorize @post if @post.update(post_params) redirect_to @post else render :edit end end ``` 就會去執行 post_policy 內的`update?`方法。 你也可以在不同的 action 裡,要求與 action 不同名的驗證: ```ruby= def publish @post = Post.find(params[:id]) authorize @post, :update? @post.publish! redirect_to @post end ``` 也可以在view裡面呼叫他: ```html= <% if policy(@post).update? %> <%= link_to "Edit post", edit_post_path(@post) %> <% end %> ``` 以上是比較基本的用法! 如果想某些 user 來做驗證,可以使用scope: ```ruby= class PostPolicy < ApplicationPolicy class Scope def initialize(user, scope) @user = user @scope = scope end def resolve if user.admin? scope.all else scope.where(published: true) end end private attr_reader :user, :scope end def update? user.admin? or not record.published? end end ``` 特別要說的是,pundit 也能處理 params: ```ruby= # in policy class PostPolicy < ApplicationPolicy def permitted_attributes if user.admin? || user.owner_of?(post) [:title, :body, :tag_list] else [:tag_list] end end end # in controller def update @post = Post.find(params[:id]) if @post.update_attributes(permitted_attributes(@post)) redirect_to @post else render :edit end end ``` 也可以針對不同action,有不同的`permitted_attributes` ```ruby= class PostPolicy < ApplicationPolicy def permitted_attributes_for_create [:title, :body] end def permitted_attributes_for_edit [:body] end end ``` 以上就是有關 pundit 的基本介紹啦!感謝各位看到這邊,若有任何建議,請各位不吝指教!我們明天見! 
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up