Module: ActionPolicy::Policy::Scoping

Includes:
Behaviours::Scoping
Included in:
Base
Defined in:
lib/action_policy/policy/scoping.rb

Overview

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)

Defined Under Namespace

Modules: ClassMethods

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Behaviours::Scoping

#authorization_scope_type_for, #authorized_scope

Class Method Details

.included(base) ⇒ Object



81
82
83
# File 'lib/action_policy/policy/scoping.rb', line 81

def included(base)
  base.extend ClassMethods
end

Instance Method Details

#apply_scope(target, type:, name: :default, scope_options: nil) ⇒ Object

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.



92
93
94
95
96
97
98
99
100
101
# 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) ⇒ Object



108
109
110
111
112
# 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) ⇒ Object



103
104
105
106
# File 'lib/action_policy/policy/scoping.rb', line 103

def resolve_scope_type(target)
  lookup_type_from_target(target) ||
    raise(ActionPolicy::UnrecognizedScopeTarget, target)
end