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