Module: ActionPolicy::Policy::Core

Includes:
Behaviours::PolicyFor
Included in:
Base
Defined in:
lib/action_policy/policy/core.rb

Overview

Core policy API

Defined Under Namespace

Modules: ClassMethods

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Behaviours::PolicyFor

#authorization_context, #authorization_namespace, #authorization_strict_namespace, #build_authorization_context, #default_authorization_policy_class, #implicit_authorization_target, #implicit_authorization_target!, #policy_for, #policy_for_cache_key

Instance Attribute Details

#recordObject (readonly)

Returns the value of attribute record.



75
76
77
# File 'lib/action_policy/policy/core.rb', line 75

def record
  @record
end

#resultObject (readonly)

Returns the value of attribute result.



75
76
77
# File 'lib/action_policy/policy/core.rb', line 75

def result
  @result
end

Class Method Details

.included(base) ⇒ Object



43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/action_policy/policy/core.rb', line 43

def included(base)
  base.extend ClassMethods

  # Generate a new class for each _policy chain_
  # in order to extend it independently
  base.module_eval do
    @result_class = Class.new(ExecutionResult)

    # we need to make this class _named_,
    # 'cause anonymous classes couldn't be marshalled
    base.const_set(:APR, @result_class)
  end
end

Instance Method Details

#__apply__(rule) ⇒ Object

This method performs the rule call. Override or extend it to provide custom functionality (such as caching, pre checks, etc.)



108
# File 'lib/action_policy/policy/core.rb', line 108

def __apply__(rule) = public_send(rule)

#allow!Object



100
101
102
103
# File 'lib/action_policy/policy/core.rb', line 100

def allow!
  result&.load true
  throw :policy_fulfilled
end

#allowed_to?(rule, record = :__undef__, **options) ⇒ Boolean

Returns a result of applying the specified rule to the specified record. Under the hood a policy class for record is resolved (unless it’s explicitly set through ‘with` option).

If record is ‘nil` then we uses the current policy.

Returns:

  • (Boolean)


125
126
127
128
129
130
131
132
133
# File 'lib/action_policy/policy/core.rb', line 125

def allowed_to?(rule, record = :__undef__, **options)
  if (record == :__undef__ || record == self.record) && options.empty?
    __apply__(resolve_rule(rule))
  else
    policy_for(record: record, **options).then do |policy|
      policy.apply(policy.resolve_rule(rule))
    end
  end
end

#apply(rule) ⇒ Object

Returns a result of applying the specified rule (true of false). Unlike simply calling a predicate rule (‘policy.manage?`), `apply` also calls pre-checks.



85
86
87
88
89
90
91
92
93
# File 'lib/action_policy/policy/core.rb', line 85

def apply(rule)
  @result = self.class.result_class.new(self.class, rule)

  catch :policy_fulfilled do
    result.load __apply__(resolve_rule(rule))
  end

  result.value
end

#check?(*args, **hargs) ⇒ Boolean

An alias for readability purposes

Returns:

  • (Boolean)


136
# File 'lib/action_policy/policy/core.rb', line 136

def check?(*args, **hargs) = allowed_to?(*args, **hargs)

#deny!Object



95
96
97
98
# File 'lib/action_policy/policy/core.rb', line 95

def deny!
  result&.load false
  throw :policy_fulfilled
end

#initialize(record = nil) ⇒ Object

NEXT_RELEASE: deprecate ‘record` arg, migrate to `record: nil`



78
79
80
# File 'lib/action_policy/policy/core.rb', line 78

def initialize(record = nil, *)
  @record = record
end

#inspect_rule(rule) ⇒ Object

Return annotated source code for the rule NOTE: require “method_source” and “prism” gems to be installed. Otherwise returns empty string.



152
# File 'lib/action_policy/policy/core.rb', line 152

def inspect_rule(rule) = PrettyPrint.print_method(self, rule)

#pp(rule) ⇒ Object

Helper for printing the annotated rule source. Useful for debugging: type ‘pp :show?` within the context of the policy to preview the rule.



157
158
159
160
161
162
163
164
165
# File 'lib/action_policy/policy/core.rb', line 157

def pp(rule)
  with_clean_result do
    # We need result to exist for `allowed_to?` to work correctly
    @result = self.class.result_class.new(self.class, rule)
    header = "#{self.class.name}##{rule}"
    source = inspect_rule(rule)
    $stdout.puts "#{header}\n#{source}"
  end
end

#resolve_rule(activity) ⇒ Object

Returns a rule name (policy method name) for activity.

By default, rule name is equal to activity name.

Raises ActionPolicy::UnknownRule when rule is not found in policy.

Raises:



143
144
145
146
147
# File 'lib/action_policy/policy/core.rb', line 143

def resolve_rule(activity)
  raise UnknownRule.new(self, activity) unless
    respond_to?(activity)
  activity
end

#with_clean_resultObject

Wrap code that could modify result to prevent the current result modification



112
113
114
115
116
117
118
# File 'lib/action_policy/policy/core.rb', line 112

def with_clean_result # :nodoc:
  was_result = @result
  yield
  @result
ensure
  @result = was_result
end