action_policy 0.4.4 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +203 -174
  3. data/README.md +5 -4
  4. data/lib/action_policy.rb +7 -1
  5. data/lib/action_policy/behaviour.rb +22 -16
  6. data/lib/action_policy/behaviours/policy_for.rb +10 -3
  7. data/lib/action_policy/behaviours/scoping.rb +2 -1
  8. data/lib/action_policy/behaviours/thread_memoized.rb +1 -3
  9. data/lib/action_policy/ext/module_namespace.rb +1 -6
  10. data/lib/action_policy/ext/policy_cache_key.rb +10 -30
  11. data/lib/action_policy/i18n.rb +1 -1
  12. data/lib/action_policy/lookup_chain.rb +29 -15
  13. data/lib/action_policy/policy/aliases.rb +7 -12
  14. data/lib/action_policy/policy/authorization.rb +8 -7
  15. data/lib/action_policy/policy/cache.rb +11 -17
  16. data/lib/action_policy/policy/core.rb +25 -12
  17. data/lib/action_policy/policy/defaults.rb +3 -9
  18. data/lib/action_policy/policy/execution_result.rb +3 -9
  19. data/lib/action_policy/policy/pre_check.rb +19 -58
  20. data/lib/action_policy/policy/reasons.rb +29 -19
  21. data/lib/action_policy/policy/scoping.rb +5 -6
  22. data/lib/action_policy/rails/controller.rb +6 -1
  23. data/lib/action_policy/rails/policy/instrumentation.rb +1 -1
  24. data/lib/action_policy/rspec/be_authorized_to.rb +5 -9
  25. data/lib/action_policy/rspec/dsl.rb +1 -1
  26. data/lib/action_policy/rspec/have_authorized_scope.rb +5 -7
  27. data/lib/action_policy/utils/pretty_print.rb +21 -24
  28. data/lib/action_policy/utils/suggest_message.rb +1 -3
  29. data/lib/action_policy/version.rb +1 -1
  30. data/lib/generators/action_policy/install/templates/{application_policy.rb → application_policy.rb.tt} +0 -0
  31. data/lib/generators/action_policy/policy/policy_generator.rb +4 -1
  32. data/lib/generators/action_policy/policy/templates/{policy.rb → policy.rb.tt} +0 -0
  33. data/lib/generators/rspec/templates/{policy_spec.rb → policy_spec.rb.tt} +0 -0
  34. data/lib/generators/test_unit/templates/{policy_test.rb → policy_test.rb.tt} +0 -0
  35. metadata +29 -119
  36. data/.gitattributes +0 -2
  37. data/.github/ISSUE_TEMPLATE.md +0 -21
  38. data/.github/PULL_REQUEST_TEMPLATE.md +0 -29
  39. data/.github/bug_report_template.rb +0 -175
  40. data/.gitignore +0 -15
  41. data/.rubocop.yml +0 -54
  42. data/.tidelift.yml +0 -6
  43. data/.travis.yml +0 -31
  44. data/Gemfile +0 -22
  45. data/Rakefile +0 -27
  46. data/action_policy.gemspec +0 -44
  47. data/benchmarks/namespaced_lookup_cache.rb +0 -74
  48. data/benchmarks/pre_checks.rb +0 -73
  49. data/bin/console +0 -14
  50. data/bin/setup +0 -8
  51. data/docs/.nojekyll +0 -0
  52. data/docs/CNAME +0 -1
  53. data/docs/README.md +0 -79
  54. data/docs/_sidebar.md +0 -27
  55. data/docs/aliases.md +0 -122
  56. data/docs/assets/docsify-search.js +0 -364
  57. data/docs/assets/docsify.min.js +0 -3
  58. data/docs/assets/fonts/FiraCode-Medium.woff +0 -0
  59. data/docs/assets/fonts/FiraCode-Regular.woff +0 -0
  60. data/docs/assets/images/banner.png +0 -0
  61. data/docs/assets/images/cache.png +0 -0
  62. data/docs/assets/images/cache.svg +0 -70
  63. data/docs/assets/images/layer.png +0 -0
  64. data/docs/assets/images/layer.svg +0 -35
  65. data/docs/assets/prism-ruby.min.js +0 -1
  66. data/docs/assets/styles.css +0 -347
  67. data/docs/assets/vue.min.css +0 -1
  68. data/docs/authorization_context.md +0 -92
  69. data/docs/behaviour.md +0 -113
  70. data/docs/caching.md +0 -291
  71. data/docs/controller_action_aliases.md +0 -109
  72. data/docs/custom_lookup_chain.md +0 -48
  73. data/docs/custom_policy.md +0 -53
  74. data/docs/debugging.md +0 -55
  75. data/docs/decorators.md +0 -27
  76. data/docs/favicon.ico +0 -0
  77. data/docs/graphql.md +0 -302
  78. data/docs/i18n.md +0 -44
  79. data/docs/index.html +0 -43
  80. data/docs/instrumentation.md +0 -84
  81. data/docs/lookup_chain.md +0 -22
  82. data/docs/namespaces.md +0 -77
  83. data/docs/non_rails.md +0 -28
  84. data/docs/pre_checks.md +0 -57
  85. data/docs/pundit_migration.md +0 -80
  86. data/docs/quick_start.md +0 -118
  87. data/docs/rails.md +0 -120
  88. data/docs/reasons.md +0 -120
  89. data/docs/scoping.md +0 -255
  90. data/docs/testing.md +0 -390
  91. data/docs/writing_policies.md +0 -107
  92. data/gemfiles/jruby.gemfile +0 -8
  93. data/gemfiles/rails42.gemfile +0 -9
  94. data/gemfiles/rails6.gemfile +0 -8
  95. data/gemfiles/railsmaster.gemfile +0 -6
  96. data/lib/action_policy/ext/string_match.rb +0 -14
  97. data/lib/action_policy/ext/yield_self_then.rb +0 -25
data/README.md CHANGED
@@ -1,5 +1,6 @@
1
1
  [![Gem Version](https://badge.fury.io/rb/action_policy.svg)](https://badge.fury.io/rb/action_policy)
2
- [![Build Status](https://travis-ci.org/palkan/action_policy.svg?branch=master)](https://travis-ci.org/palkan/action_policy)
2
+ ![Build](https://github.com/palkan/action_policy/workflows/Build/badge.svg)
3
+ ![JRuby Build](https://github.com/palkan/action_policy/workflows/JRuby%20Build/badge.svg)
3
4
  [![Documentation](https://img.shields.io/badge/docs-link-brightgreen.svg)](https://actionpolicy.evilmartians.io)
4
5
 
5
6
  # Action Policy
@@ -21,7 +22,6 @@ Composable. Extensible. Performant.
21
22
 
22
23
  - RailsConf, 2018 "Access Denied" talk ([video](https://www.youtube.com/watch?v=NVwx0DARDis), [slides](https://speakerdeck.com/palkan/railsconf-2018-access-denied-the-missing-guide-to-authorization-in-rails))
23
24
 
24
-
25
25
  ## Integrations
26
26
 
27
27
  - GraphQL Ruby ([`action_policy-graphql`](https://github.com/palkan/action_policy-graphql))
@@ -36,7 +36,9 @@ gem "action_policy", "~> 0.4.0"
36
36
 
37
37
  And then execute:
38
38
 
39
- $ bundle
39
+ ```sh
40
+ bundle install
41
+ ```
40
42
 
41
43
  ## Usage
42
44
 
@@ -89,7 +91,6 @@ end
89
91
 
90
92
  \* See [Non-Rails Usage](docs/non_rails.md) on how to add `authorize!` to any Ruby project.
91
93
 
92
-
93
94
  When authorization is successful (i.e., the corresponding rule returns `true`), nothing happens, but in case of authorization failure `ActionPolicy::Unauthorized` error is raised.
94
95
 
95
96
  There is also an `allowed_to?` method which returns `true` or `false`, and could be used, in views, for example:
@@ -1,5 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "ruby-next"
4
+
5
+ require "ruby-next/language/setup"
6
+ RubyNext::Language.setup_gem_load_path(transpile: true)
7
+
3
8
  # ActionPolicy is an authorization framework for Ruby/Rails applications.
4
9
  #
5
10
  # It provides a way to write access policies and helpers to check these policies
@@ -30,8 +35,9 @@ module ActionPolicy
30
35
  attr_accessor :cache_store
31
36
 
32
37
  # Find a policy class for a target
33
- def lookup(target, allow_nil: false, **options)
38
+ def lookup(target, allow_nil: false, default: nil, **options)
34
39
  LookupChain.call(target, **options) ||
40
+ default ||
35
41
  (allow_nil ? nil : raise(NotFound, target))
36
42
  end
37
43
  end
@@ -35,12 +35,7 @@ module ActionPolicy
35
35
  #
36
36
  # Raises `ActionPolicy::Unauthorized` if check failed.
37
37
  def authorize!(record = :__undef__, to:, **options)
38
- record = implicit_authorization_target! if record == :__undef__
39
- raise ArgumentError, "Record must be specified" if record.nil?
40
-
41
- options[:context] && (options[:context] = authorization_context.merge(options[:context]))
42
-
43
- policy = policy_for(record: record, **options)
38
+ policy = lookup_authorization_policy(record, **options)
44
39
 
45
40
  Authorizer.call(policy, authorization_rule_for(policy, to))
46
41
  end
@@ -49,14 +44,17 @@ module ActionPolicy
49
44
  #
50
45
  # Returns true of false.
51
46
  def allowed_to?(rule, record = :__undef__, **options)
52
- record = implicit_authorization_target! if record == :__undef__
53
- raise ArgumentError, "Record must be specified" if record.nil?
47
+ policy = lookup_authorization_policy(record, **options)
54
48
 
55
- options[:context] && (options[:context] = authorization_context.merge(options[:context]))
49
+ policy.apply(authorization_rule_for(policy, rule))
50
+ end
56
51
 
57
- policy = policy_for(record: record, **options)
52
+ # Returns the authorization result object after applying a specified rule to a record.
53
+ def allowance_to(rule, record = :__undef__, **options)
54
+ policy = lookup_authorization_policy(record, **options)
58
55
 
59
56
  policy.apply(authorization_rule_for(policy, rule))
57
+ policy.result
60
58
  end
61
59
 
62
60
  def authorization_context
@@ -75,6 +73,15 @@ module ActionPolicy
75
73
  policy.resolve_rule(rule)
76
74
  end
77
75
 
76
+ def lookup_authorization_policy(record, **options) # :nodoc:
77
+ record = implicit_authorization_target! if record == :__undef__
78
+ raise ArgumentError, "Record must be specified" if record.nil?
79
+
80
+ options[:context] && (options[:context] = authorization_context.merge(options[:context]))
81
+
82
+ policy_for(record: record, **options)
83
+ end
84
+
78
85
  module ClassMethods # :nodoc:
79
86
  # Configure authorization context.
80
87
  #
@@ -97,12 +104,11 @@ module ActionPolicy
97
104
  def authorization_targets
98
105
  return @authorization_targets if instance_variable_defined?(:@authorization_targets)
99
106
 
100
- @authorization_targets =
101
- if superclass.respond_to?(:authorization_targets)
102
- superclass.authorization_targets.dup
103
- else
104
- {}
105
- end
107
+ if superclass.respond_to?(:authorization_targets)
108
+ superclass.authorization_targets.dup
109
+ else
110
+ {}
111
+ end => @authorization_targets
106
112
  end
107
113
  end
108
114
  end
@@ -8,8 +8,11 @@ module ActionPolicy
8
8
  using ActionPolicy::Ext::PolicyCacheKey
9
9
 
10
10
  # Returns policy instance for the record.
11
- def policy_for(record:, with: nil, namespace: authorization_namespace, context: authorization_context, allow_nil: false)
12
- policy_class = with || ::ActionPolicy.lookup(record, namespace: namespace, context: context, allow_nil: allow_nil)
11
+ def policy_for(record:, with: nil, namespace: authorization_namespace, context: authorization_context, allow_nil: false, default: default_authorization_policy_class)
12
+ policy_class = with || ::ActionPolicy.lookup(
13
+ record,
14
+ **{namespace, context, allow_nil, default}
15
+ )
13
16
  policy_class&.new(record, **context)
14
17
  end
15
18
 
@@ -21,6 +24,10 @@ module ActionPolicy
21
24
  # override to provide specific authorization namespace
22
25
  end
23
26
 
27
+ def default_authorization_policy_class
28
+ # override to provide a policy class use when no policy found
29
+ end
30
+
24
31
  # Override this method to provide implicit authorization target
25
32
  # that would be used in case `record` is not specified in
26
33
  # `authorize!` and `allowed_to?` call.
@@ -46,7 +53,7 @@ module ActionPolicy
46
53
 
47
54
  def policy_for_cache_key(record:, with: nil, namespace: nil, context: authorization_context, **)
48
55
  record_key = record._policy_cache_key(use_object_id: true)
49
- context_key = context.values.map { |v| v._policy_cache_key(use_object_id: true) }.join(".")
56
+ context_key = context.values.map { _1._policy_cache_key(use_object_id: true) }.join(".")
50
57
 
51
58
  "#{namespace}/#{with}/#{context_key}/#{record_key}"
52
59
  end
@@ -17,8 +17,9 @@ module ActionPolicy
17
17
  policy ||= policy_for(record: implicit_authorization_target!, **options)
18
18
 
19
19
  type ||= authorization_scope_type_for(policy, target)
20
+ name = as
20
21
 
21
- Authorizer.scopify(target, policy, type: type, name: as, scope_options: scope_options)
22
+ Authorizer.scopify(target, policy, **{type, name, scope_options})
22
23
  end
23
24
 
24
25
  # For backward compatibility
@@ -7,9 +7,7 @@ module ActionPolicy
7
7
  class << self
8
8
  attr_writer :enabled
9
9
 
10
- def enabled?
11
- @enabled == true
12
- end
10
+ def enabled?() = @enabled == true
13
11
 
14
12
  def fetch(key)
15
13
  return yield unless enabled?
@@ -9,11 +9,6 @@ module ActionPolicy
9
9
  using ActionPolicy::Ext::StringConstantize
10
10
  end
11
11
 
12
- unless "".respond_to?(:match?)
13
- require "action_policy/ext/string_match"
14
- using ActionPolicy::Ext::StringMatch
15
- end
16
-
17
12
  module Ext
18
13
  def namespace
19
14
  return unless name&.match?(/[^^]::/)
@@ -23,7 +18,7 @@ module ActionPolicy
23
18
  end
24
19
 
25
20
  # See https://github.com/jruby/jruby/issues/5220
26
- ::Module.include(Ext) if RUBY_PLATFORM =~ /java/i
21
+ ::Module.include(Ext) if RUBY_PLATFORM.match?(/java/i)
27
22
 
28
23
  refine Module do
29
24
  include Ext
@@ -27,65 +27,45 @@ module ActionPolicy
27
27
  end
28
28
 
29
29
  refine NilClass do
30
- def _policy_cache_key(*)
31
- ""
32
- end
30
+ def _policy_cache_key(*) = ""
33
31
  end
34
32
 
35
33
  refine TrueClass do
36
- def _policy_cache_key(*)
37
- "t"
38
- end
34
+ def _policy_cache_key(*) = "t"
39
35
  end
40
36
 
41
37
  refine FalseClass do
42
- def _policy_cache_key(*)
43
- "f"
44
- end
38
+ def _policy_cache_key(*) = "f"
45
39
  end
46
40
 
47
41
  refine String do
48
- def _policy_cache_key(*)
49
- self
50
- end
42
+ def _policy_cache_key(*) = self
51
43
  end
52
44
 
53
45
  refine Symbol do
54
- def _policy_cache_key(*)
55
- to_s
56
- end
46
+ def _policy_cache_key(*) = to_s
57
47
  end
58
48
 
59
49
  if RUBY_PLATFORM.match?(/java/i)
60
50
  refine Integer do
61
- def _policy_cache_key(*)
62
- to_s
63
- end
51
+ def _policy_cache_key(*) = to_s
64
52
  end
65
53
 
66
54
  refine Float do
67
- def _policy_cache_key(*)
68
- to_s
69
- end
55
+ def _policy_cache_key(*) = to_s
70
56
  end
71
57
  else
72
58
  refine Numeric do
73
- def _policy_cache_key(*)
74
- to_s
75
- end
59
+ def _policy_cache_key(*) = to_s
76
60
  end
77
61
  end
78
62
 
79
63
  refine Time do
80
- def _policy_cache_key(*)
81
- to_s
82
- end
64
+ def _policy_cache_key(*) = to_s
83
65
  end
84
66
 
85
67
  refine Module do
86
- def _policy_cache_key(*)
87
- name
88
- end
68
+ def _policy_cache_key(*) = name
89
69
  end
90
70
  end
91
71
  end
@@ -21,7 +21,7 @@ module ActionPolicy
21
21
  private
22
22
 
23
23
  def candidates_for(policy_class, rule)
24
- policy_hierarchy = policy_class.ancestors.select { |klass| klass.respond_to?(:identifier) }
24
+ policy_hierarchy = policy_class.ancestors.select { _1.respond_to?(:identifier) }
25
25
  [
26
26
  *policy_hierarchy.map { |klass| :"policy.#{klass.identifier}.#{rule}" },
27
27
  :"policy.#{rule}",
@@ -24,14 +24,26 @@ module ActionPolicy
24
24
  class << self
25
25
  attr_reader :store
26
26
 
27
- def fetch(namespace, policy)
27
+ def put_if_absent(scope, namespace, policy)
28
+ local_store = store[scope][namespace]
29
+ return local_store[policy] if local_store[policy]
30
+ local_store[policy] ||= yield
31
+ end
32
+
33
+ def fetch(namespace, policy, strict:, &block)
28
34
  return yield unless LookupChain.namespace_cache_enabled?
29
- return store[namespace][policy] if store[namespace].key?(policy)
30
- store[namespace][policy] ||= yield
35
+
36
+ if strict
37
+ put_if_absent(:strict, namespace, policy, &block)
38
+ else
39
+ cached_policy = put_if_absent(:strict, namespace, policy, &block)
40
+ put_if_absent(:flexible, namespace, policy) { cached_policy }
41
+ end
31
42
  end
32
43
 
33
44
  def clear
34
- @store = Hash.new { |h, k| h[k] = {} }
45
+ hash = Hash.new { |h, k| h[k] = {} }
46
+ @store = {strict: hash, flexible: hash.clone}
35
47
  end
36
48
  end
37
49
 
@@ -53,23 +65,23 @@ module ActionPolicy
53
65
 
54
66
  private
55
67
 
56
- def lookup_within_namespace(policy_name, namespace)
68
+ def lookup_within_namespace(policy_name, namespace, strict: false)
57
69
  return unless namespace
58
- NamespaceCache.fetch(namespace.name, policy_name) do
70
+ NamespaceCache.fetch(namespace.name, policy_name, strict: strict) do
59
71
  mod = namespace
60
-
61
72
  loop do
62
73
  policy = "#{mod.name}::#{policy_name}".safe_constantize
63
-
64
74
  break policy unless policy.nil?
65
-
66
75
  mod = mod.namespace
67
-
68
- break if mod.nil?
76
+ break if mod.nil? || strict
69
77
  end
70
78
  end
71
79
  end
72
80
 
81
+ def objectify_policy(policy_name, strict: false)
82
+ policy_name.safe_constantize unless strict
83
+ end
84
+
73
85
  def policy_class_name_for(record)
74
86
  return record.policy_name.to_s if record.respond_to?(:policy_name)
75
87
 
@@ -112,19 +124,21 @@ module ActionPolicy
112
124
  }
113
125
 
114
126
  # Infer from passed symbol
115
- SYMBOL_LOOKUP = ->(record, namespace: nil, **) {
127
+ SYMBOL_LOOKUP = ->(record, namespace: nil, strict_namespace: false, **) {
116
128
  next unless record.is_a?(Symbol)
117
129
 
118
130
  policy_name = "#{record.camelize}Policy"
119
- lookup_within_namespace(policy_name, namespace) || policy_name.safe_constantize
131
+ lookup_within_namespace(policy_name, namespace, strict: strict_namespace) ||
132
+ objectify_policy(policy_name, strict: strict_namespace)
120
133
  }
121
134
 
122
135
  # (Optional) Infer using String#classify if available
123
- CLASSIFY_SYMBOL_LOOKUP = ->(record, namespace: nil, **) {
136
+ CLASSIFY_SYMBOL_LOOKUP = ->(record, namespace: nil, strict_namespace: false, **) {
124
137
  next unless record.is_a?(Symbol)
125
138
 
126
139
  policy_name = "#{record.to_s.classify}Policy"
127
- lookup_within_namespace(policy_name, namespace) || policy_name.safe_constantize
140
+ lookup_within_namespace(policy_name, namespace, strict: strict_namespace) ||
141
+ objectify_policy(policy_name, strict: strict_namespace)
128
142
  }
129
143
 
130
144
  self.chain = [
@@ -46,23 +46,18 @@ module ActionPolicy
46
46
  end
47
47
  end
48
48
 
49
- def lookup_alias(rule)
50
- rules_aliases[rule]
51
- end
49
+ def lookup_alias(rule) = rules_aliases[rule]
52
50
 
53
- def lookup_default_rule
54
- rules_aliases[DEFAULT]
55
- end
51
+ def lookup_default_rule() = rules_aliases[DEFAULT]
56
52
 
57
53
  def rules_aliases
58
54
  return @rules_aliases if instance_variable_defined?(:@rules_aliases)
59
55
 
60
- @rules_aliases =
61
- if superclass.respond_to?(:rules_aliases)
62
- superclass.rules_aliases.dup
63
- else
64
- {}
65
- end
56
+ if superclass.respond_to?(:rules_aliases)
57
+ superclass.rules_aliases.dup
58
+ else
59
+ {}
60
+ end => @rules_aliases
66
61
  end
67
62
 
68
63
  def method_added(name)
@@ -63,8 +63,10 @@ module ActionPolicy
63
63
 
64
64
  module ClassMethods # :nodoc:
65
65
  def authorize(*ids, allow_nil: false, optional: false)
66
+ allow_nil ||= optional
67
+
66
68
  ids.each do |id|
67
- authorization_targets[id] = {allow_nil: allow_nil || optional, optional: optional}
69
+ authorization_targets[id] = {allow_nil, optional}
68
70
  end
69
71
 
70
72
  attr_reader(*ids)
@@ -73,12 +75,11 @@ module ActionPolicy
73
75
  def authorization_targets
74
76
  return @authorization_targets if instance_variable_defined?(:@authorization_targets)
75
77
 
76
- @authorization_targets =
77
- if superclass.respond_to?(:authorization_targets)
78
- superclass.authorization_targets.dup
79
- else
80
- {}
81
- end
78
+ if superclass.respond_to?(:authorization_targets)
79
+ superclass.authorization_targets.dup
80
+ else
81
+ {}
82
+ end => @authorization_targets
82
83
  end
83
84
  end
84
85
  end
@@ -3,16 +3,13 @@
3
3
  require "action_policy/version"
4
4
 
5
5
  module ActionPolicy # :nodoc:
6
+ using RubyNext
7
+
6
8
  # By default cache namespace (or prefix) contains major and minor version of the gem
7
9
  CACHE_NAMESPACE = "acp:#{ActionPolicy::VERSION.split(".").take(2).join(".")}"
8
10
 
9
- require "action_policy/ext/yield_self_then"
10
11
  require "action_policy/ext/policy_cache_key"
11
12
 
12
- unless "".respond_to?(:then)
13
- require "action_policy/ext/yield_self_then"
14
- using ActionPolicy::Ext::YieldSelfThen
15
- end
16
13
  using ActionPolicy::Ext::PolicyCacheKey
17
14
 
18
15
  module Policy
@@ -26,15 +23,13 @@ module ActionPolicy # :nodoc:
26
23
  end
27
24
  end
28
25
 
29
- def cache_namespace
30
- ActionPolicy::CACHE_NAMESPACE
31
- end
26
+ def cache_namespace() = ActionPolicy::CACHE_NAMESPACE
32
27
 
33
28
  def cache_key(*parts)
34
29
  [
35
30
  cache_namespace,
36
31
  *parts
37
- ].map { |part| part._policy_cache_key }.join("/")
32
+ ].map { _1._policy_cache_key }.join("/")
38
33
  end
39
34
 
40
35
  def rule_cache_key(rule)
@@ -47,7 +42,7 @@ module ActionPolicy # :nodoc:
47
42
  end
48
43
 
49
44
  def context_cache_key
50
- authorization_context.map { |_k, v| v._policy_cache_key.to_s }.join("/")
45
+ authorization_context.map { _2._policy_cache_key.to_s }.join("/")
51
46
  end
52
47
 
53
48
  def apply_with_cache(rule)
@@ -79,7 +74,7 @@ module ActionPolicy # :nodoc:
79
74
  res = store.read(key)
80
75
  next res unless res.nil?
81
76
  res = yield
82
- store.write(key, res, **options)
77
+ store.write(key, res, options)
83
78
  res
84
79
  end
85
80
  end
@@ -94,12 +89,11 @@ module ActionPolicy # :nodoc:
94
89
  def cached_rules
95
90
  return @cached_rules if instance_variable_defined?(:@cached_rules)
96
91
 
97
- @cached_rules =
98
- if superclass.respond_to?(:cached_rules)
99
- superclass.cached_rules.dup
100
- else
101
- {}
102
- end
92
+ if superclass.respond_to?(:cached_rules)
93
+ superclass.cached_rules.dup
94
+ else
95
+ {}
96
+ end => @cached_rules
103
97
  end
104
98
  end
105
99
  end