處理大量的能力

一旦能力定義的數量開始增加,處理 Ability 檔案就變得越來越困難。

處理這些問題的第一個策略是將能力轉換為有意義的方法,如下例所示:

class Ability
  include CanCan::Ability

  def initialize(user)
    anyone_abilities 

    if user
      if user.admin?
        admin_abilities
      else
        authenticated_abilities
      end
    else
      guest_abilities
    end
  end

  private
  
  def anyone_abilities
    # define abilities for everyone, both logged users and visitors
  end

  def guest_abilities
    # define abilities for visitors only
  end

  def authenticated_abilities
    # define abilities for logged users only
  end

  def admin_abilities
    # define abilities for admins only
  end
end

一旦這個類變得足夠大,你可以嘗試將它分成不同的類來處理不同的職責,如下所示:

# app/models/ability.rb
class Ability
  include CanCan::Ability

  def initialize(user)
    self.merge Abilities::Everyone.new(user)

    if user
      if user.admin?
        self.merge Abilities::Admin.new(user)
      else
        self.merge Abilities::Authenticated.new(user)
      end
    else
      self.merge Abilities::Guest.new(user)
    end
  end
end

然後將這些類定義為:

# app/models/abilities/guest.rb
module Abilities
  class Guest
    include CanCan::Ability

    def initialize(user)
      # Abilities for anonymous visitors only
    end
  end
end

Abilities::AuthenticatedAbilities::Admin 或其他任何其他人一樣。