module ActionPolicy::Policy::Scoping

Scoping is used to modify the _object under authorization_.

The most common situation is when you want to scope the collection depending on the current user permissions.

For example:

class ApplicationPolicy < ActionPolicy::Base
  # Scoping only makes sense when you have the authorization context
  authorize :user

  # :relation here is a scoping type
  scope_for :relation do |relation|
    # authorization context is available within a scope
    if user.admin?
      relation
    else
      relation.publicly_visible
    end
  end
end

base_scope = User.all
authorized_scope = ApplicantPolicy.new(user: user)
 .apply_scope(base_scope, type: :relation)

Public Class Methods

included(base) click to toggle source
# File lib/action_policy/policy/scoping.rb, line 81
def included(base)
  base.extend ClassMethods
end

Public Instance Methods

apply_scope(target, type:, name: :default, scope_options: nil) click to toggle source

Pass target to the scope handler of the specified type and name. If `name` is not specified then `:default` name is used. If `type` is not specified then we try to infer the type from the target class.

# File lib/action_policy/policy/scoping.rb, line 92
def apply_scope(target, type:, name: :default, scope_options: nil)
  raise ActionPolicy::UnknownScopeType.new(self.class, type) unless
    self.class.scoping_handlers.key?(type)

  raise ActionPolicy::UnknownNamedScope.new(self.class, type, name) unless
    self.class.scoping_handlers[type].key?(name)

  mid = :"__scoping__#{type}__#{name}"
  scope_options ? send(mid, target, **scope_options) : send(mid, target)
end
lookup_type_from_target(target) click to toggle source
# File lib/action_policy/policy/scoping.rb, line 108
def lookup_type_from_target(target)
  self.class.scope_matchers.detect do |(_type, matcher)|
    matcher === target
  end&.first
end
resolve_scope_type(target) click to toggle source
# File lib/action_policy/policy/scoping.rb, line 103
def resolve_scope_type(target)
  lookup_type_from_target(target) ||
    raise(ActionPolicy::UnrecognizedScopeTarget, target)
end