snfoil 0.1.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.
- checksums.yaml +7 -0
- data/.gitignore +8 -0
- data/.rubocop.yml +28 -0
- data/.ruby-version +1 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +112 -0
- data/LICENSE.txt +21 -0
- data/README.md +43 -0
- data/Rakefile +4 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/lib/sn_foil/adapters/orms/active_record.rb +30 -0
- data/lib/sn_foil/adapters/orms/base_adapter.rb +29 -0
- data/lib/sn_foil/context.rb +24 -0
- data/lib/sn_foil/contexts/build_context_concern.rb +43 -0
- data/lib/sn_foil/contexts/change_context_concern.rb +104 -0
- data/lib/sn_foil/contexts/create_context_concern.rb +147 -0
- data/lib/sn_foil/contexts/destroy_context_concern.rb +141 -0
- data/lib/sn_foil/contexts/index_context_concern.rb +45 -0
- data/lib/sn_foil/contexts/setup_context_concern.rb +80 -0
- data/lib/sn_foil/contexts/show_context_concern.rb +35 -0
- data/lib/sn_foil/contexts/update_context_concern.rb +144 -0
- data/lib/sn_foil/policy.rb +48 -0
- data/lib/sn_foil/searcher.rb +110 -0
- data/lib/sn_foil/version.rb +5 -0
- data/lib/sn_foil.rb +41 -0
- data/snfoil.gemspec +36 -0
- metadata +212 -0
@@ -0,0 +1,147 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_support/concern'
|
4
|
+
require_relative './setup_context_concern'
|
5
|
+
require_relative './change_context_concern'
|
6
|
+
|
7
|
+
module SnFoil
|
8
|
+
module Contexts
|
9
|
+
module CreateContextConcern # rubocop:disable Metrics/ModuleLength
|
10
|
+
extend ActiveSupport::Concern
|
11
|
+
|
12
|
+
included do
|
13
|
+
include SetupContextConcern
|
14
|
+
include ChangeContextConcern
|
15
|
+
end
|
16
|
+
|
17
|
+
class_methods do
|
18
|
+
attr_reader :i_before_create_hooks, :i_after_create_hooks, :i_after_create_success_hooks, :i_after_create_failure_hooks
|
19
|
+
def create(params:, user: nil, **options)
|
20
|
+
new(user).create(**options, params: params)
|
21
|
+
end
|
22
|
+
|
23
|
+
def before_create(method = nil, **options, &block)
|
24
|
+
raise ArgumentError, '#on_create requires either a method name or a block' if method.nil? && block.nil?
|
25
|
+
|
26
|
+
(@i_before_create_hooks ||= []) << { method: method, block: block, if: options[:if], unless: options[:unless] }
|
27
|
+
end
|
28
|
+
|
29
|
+
def after_create(method = nil, **options, &block)
|
30
|
+
raise ArgumentError, '#after_create requires either a method name or a block' if method.nil? && block.nil?
|
31
|
+
|
32
|
+
(@i_after_create_hooks ||= []) << { method: method, block: block, if: options[:if], unless: options[:unless] }
|
33
|
+
end
|
34
|
+
|
35
|
+
def after_create_success(method = nil, **options, &block)
|
36
|
+
raise ArgumentError, '#after_create_success requires either a method name or a block' if method.nil? && block.nil?
|
37
|
+
|
38
|
+
(@i_after_create_success_hooks ||= []) << { method: method, block: block, if: options[:if], unless: options[:unless] }
|
39
|
+
end
|
40
|
+
|
41
|
+
def after_create_failure(method = nil, **options, &block)
|
42
|
+
raise ArgumentError, '#after_create_failure requires either a method name or a block' if method.nil? && block.nil?
|
43
|
+
|
44
|
+
(@i_after_create_failure_hooks ||= []) << { method: method, block: block, if: options[:if], unless: options[:unless] }
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def setup_create_object(params: {}, object: nil, **options)
|
49
|
+
object = if object
|
50
|
+
wrap_object(object)
|
51
|
+
else
|
52
|
+
klass = options.fetch(:model) { model }
|
53
|
+
wrap_object(klass).new
|
54
|
+
end
|
55
|
+
|
56
|
+
object.attributes = params
|
57
|
+
options.merge! object: object
|
58
|
+
end
|
59
|
+
|
60
|
+
def create(**options)
|
61
|
+
options[:action] = :create
|
62
|
+
options = setup_change(setup_create(**options))
|
63
|
+
options = setup_create_object(**options)
|
64
|
+
authorize(options[:object], :create?, **options)
|
65
|
+
options = create_hooks(**options)
|
66
|
+
unwrap_object(options[:object])
|
67
|
+
end
|
68
|
+
|
69
|
+
def setup_create(**options)
|
70
|
+
options
|
71
|
+
end
|
72
|
+
|
73
|
+
def before_create(**options)
|
74
|
+
options
|
75
|
+
end
|
76
|
+
|
77
|
+
def after_create(**options)
|
78
|
+
options
|
79
|
+
end
|
80
|
+
|
81
|
+
def after_create_success(**options)
|
82
|
+
options
|
83
|
+
end
|
84
|
+
|
85
|
+
def after_create_failure(**options)
|
86
|
+
options
|
87
|
+
end
|
88
|
+
|
89
|
+
def before_create_hooks
|
90
|
+
self.class.i_before_create_hooks || []
|
91
|
+
end
|
92
|
+
|
93
|
+
def after_create_hooks
|
94
|
+
self.class.i_after_create_hooks || []
|
95
|
+
end
|
96
|
+
|
97
|
+
def after_create_success_hooks
|
98
|
+
self.class.i_after_create_success_hooks || []
|
99
|
+
end
|
100
|
+
|
101
|
+
def after_create_failure_hooks
|
102
|
+
self.class.i_after_create_failure_hooks || []
|
103
|
+
end
|
104
|
+
|
105
|
+
private
|
106
|
+
|
107
|
+
# This method is private to help protect the order of execution of hooks
|
108
|
+
def create_hooks(options)
|
109
|
+
options = before_create_save(**options)
|
110
|
+
options = if options[:object].save
|
111
|
+
after_create_save_success(**options)
|
112
|
+
else
|
113
|
+
after_create_save_failure(**options)
|
114
|
+
end
|
115
|
+
after_create_save(**options)
|
116
|
+
end
|
117
|
+
|
118
|
+
def before_create_save(**options)
|
119
|
+
options = before_create(**options)
|
120
|
+
options = before_create_hooks.reduce(options) { |opts, hook| run_hook(hook, opts) }
|
121
|
+
options = before_change(**options)
|
122
|
+
before_change_hooks.reduce(options) { |opts, hook| run_hook(hook, opts) }
|
123
|
+
end
|
124
|
+
|
125
|
+
def after_create_save(**options)
|
126
|
+
options = after_create(**options)
|
127
|
+
options = after_create_hooks.reduce(options) { |opts, hook| run_hook(hook, opts) }
|
128
|
+
options = after_change(**options)
|
129
|
+
after_change_hooks.reduce(options) { |opts, hook| run_hook(hook, opts) }
|
130
|
+
end
|
131
|
+
|
132
|
+
def after_create_save_success(**options)
|
133
|
+
options = after_create_success(**options)
|
134
|
+
options = after_create_success_hooks.reduce(options) { |opts, hook| run_hook(hook, opts) }
|
135
|
+
options = after_change_success(**options)
|
136
|
+
after_change_success_hooks.reduce(options) { |opts, hook| run_hook(hook, opts) }
|
137
|
+
end
|
138
|
+
|
139
|
+
def after_create_save_failure(**options)
|
140
|
+
options = after_create_failure(**options)
|
141
|
+
options = after_create_failure_hooks.reduce(options) { |opts, hook| run_hook(hook, opts) }
|
142
|
+
options = after_change_failure(**options)
|
143
|
+
after_change_failure_hooks.reduce(options) { |opts, hook| run_hook(hook, opts) }
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
@@ -0,0 +1,141 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_support/concern'
|
4
|
+
require_relative './setup_context_concern'
|
5
|
+
require_relative './change_context_concern'
|
6
|
+
|
7
|
+
module SnFoil
|
8
|
+
module Contexts
|
9
|
+
module DestroyContextConcern
|
10
|
+
extend ActiveSupport::Concern
|
11
|
+
|
12
|
+
included do
|
13
|
+
include SetupContextConcern
|
14
|
+
include ChangeContextConcern
|
15
|
+
end
|
16
|
+
|
17
|
+
class_methods do
|
18
|
+
attr_reader :i_before_destroy_hooks, :i_after_destroy_hooks, :i_after_destroy_success_hooks, :i_after_destroy_failure_hooks
|
19
|
+
def destroy(id:, user: nil, **options)
|
20
|
+
new(user).destroy(**options, id: id)
|
21
|
+
end
|
22
|
+
|
23
|
+
def before_destroy(method = nil, **options, &block)
|
24
|
+
raise ArgumentError, '#on_destroy requires either a method name or a block' if method.nil? && block.nil?
|
25
|
+
|
26
|
+
(@i_before_destroy_hooks ||= []) << { method: method, block: block, if: options[:if], unless: options[:unless] }
|
27
|
+
end
|
28
|
+
|
29
|
+
def after_destroy(method = nil, **options, &block)
|
30
|
+
raise ArgumentError, '#after_destroy requires either a method name or a block' if method.nil? && block.nil?
|
31
|
+
|
32
|
+
(@i_after_destroy_hooks ||= []) << { method: method, block: block, if: options[:if], unless: options[:unless] }
|
33
|
+
end
|
34
|
+
|
35
|
+
def after_destroy_success(method = nil, **options, &block)
|
36
|
+
raise ArgumentError, '#after_destroy_success requires either a method name or a block' if method.nil? && block.nil?
|
37
|
+
|
38
|
+
(@i_after_destroy_success_hooks ||= []) << { method: method, block: block, if: options[:if], unless: options[:unless] }
|
39
|
+
end
|
40
|
+
|
41
|
+
def after_destroy_failure(method = nil, **options, &block)
|
42
|
+
raise ArgumentError, '#after_destroy_failure requires either a method name or a block' if method.nil? && block.nil?
|
43
|
+
|
44
|
+
(@i_after_destroy_failure_hooks ||= []) << { method: method, block: block, if: options[:if], unless: options[:unless] }
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def setup_destroy_object(id: nil, object: nil, **options)
|
49
|
+
raise ArgumentError, 'one of the following keywords is required: id, object' unless id || object
|
50
|
+
|
51
|
+
options.merge! object: wrap_object(object || scope.resolve.find(id))
|
52
|
+
end
|
53
|
+
|
54
|
+
def destroy(**options)
|
55
|
+
options[:action] = :destroy
|
56
|
+
options = setup_destroy(setup_change(**options))
|
57
|
+
options = setup_destroy_object(**options)
|
58
|
+
authorize(options[:object], :destroy?, **options)
|
59
|
+
options = destroy_hooks(**options)
|
60
|
+
unwrap_object(options[:object])
|
61
|
+
end
|
62
|
+
|
63
|
+
def setup_destroy(**options)
|
64
|
+
options
|
65
|
+
end
|
66
|
+
|
67
|
+
def before_destroy(**options)
|
68
|
+
options
|
69
|
+
end
|
70
|
+
|
71
|
+
def after_destroy(**options)
|
72
|
+
options
|
73
|
+
end
|
74
|
+
|
75
|
+
def after_destroy_success(**options)
|
76
|
+
options
|
77
|
+
end
|
78
|
+
|
79
|
+
def after_destroy_failure(**options)
|
80
|
+
options
|
81
|
+
end
|
82
|
+
|
83
|
+
def before_destroy_hooks
|
84
|
+
self.class.i_before_destroy_hooks || []
|
85
|
+
end
|
86
|
+
|
87
|
+
def after_destroy_hooks
|
88
|
+
self.class.i_after_destroy_hooks || []
|
89
|
+
end
|
90
|
+
|
91
|
+
def after_destroy_success_hooks
|
92
|
+
self.class.i_after_destroy_success_hooks || []
|
93
|
+
end
|
94
|
+
|
95
|
+
def after_destroy_failure_hooks
|
96
|
+
self.class.i_after_destroy_failure_hooks || []
|
97
|
+
end
|
98
|
+
|
99
|
+
private
|
100
|
+
|
101
|
+
# This method is private to help protect the order of execution of hooks
|
102
|
+
def destroy_hooks(options)
|
103
|
+
options = before_destroy_save(options)
|
104
|
+
options = if options[:object].destroy
|
105
|
+
after_destroy_save_success(options)
|
106
|
+
else
|
107
|
+
after_destroy_save_failure(options)
|
108
|
+
end
|
109
|
+
after_destroy_save(options)
|
110
|
+
end
|
111
|
+
|
112
|
+
def before_destroy_save(options)
|
113
|
+
options = before_destroy(**options)
|
114
|
+
options = before_destroy_hooks.reduce(options) { |opts, hook| run_hook(hook, **opts) }
|
115
|
+
options = before_change(**options)
|
116
|
+
before_change_hooks.reduce(options) { |opts, hook| run_hook(hook, **opts) }
|
117
|
+
end
|
118
|
+
|
119
|
+
def after_destroy_save(options)
|
120
|
+
options = after_destroy(**options)
|
121
|
+
options = after_destroy_hooks.reduce(options) { |opts, hook| run_hook(hook, **opts) }
|
122
|
+
options = after_change(**options)
|
123
|
+
after_change_hooks.reduce(options) { |opts, hook| run_hook(hook, **opts) }
|
124
|
+
end
|
125
|
+
|
126
|
+
def after_destroy_save_success(options)
|
127
|
+
options = after_destroy_success(**options)
|
128
|
+
options = after_destroy_success_hooks.reduce(options) { |opts, hook| run_hook(hook, **opts) }
|
129
|
+
options = after_change_success(**options)
|
130
|
+
after_change_success_hooks.reduce(options) { |opts, hook| run_hook(hook, **opts) }
|
131
|
+
end
|
132
|
+
|
133
|
+
def after_destroy_save_failure(options)
|
134
|
+
options = after_destroy_failure(**options)
|
135
|
+
options = after_destroy_failure_hooks.reduce(options) { |opts, hook| run_hook(hook, **opts) }
|
136
|
+
options = after_change_failure(**options)
|
137
|
+
after_change_failure_hooks.reduce(options) { |opts, hook| run_hook(hook, **opts) }
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_support/concern'
|
4
|
+
require_relative './change_context_concern'
|
5
|
+
|
6
|
+
module SnFoil
|
7
|
+
module Contexts
|
8
|
+
module IndexContextConcern
|
9
|
+
extend ActiveSupport::Concern
|
10
|
+
|
11
|
+
included do
|
12
|
+
include SetupContextConcern
|
13
|
+
end
|
14
|
+
|
15
|
+
class_methods do
|
16
|
+
attr_reader :i_searcher
|
17
|
+
|
18
|
+
def index(params: {}, user: nil, **options)
|
19
|
+
new(user).index(**options, params: params)
|
20
|
+
end
|
21
|
+
|
22
|
+
def searcher(klass = nil)
|
23
|
+
@i_searcher = klass
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def searcher
|
28
|
+
self.class.i_searcher
|
29
|
+
end
|
30
|
+
|
31
|
+
def index(params:, **options)
|
32
|
+
options[:action] = :index
|
33
|
+
options = setup_index(**options)
|
34
|
+
options.fetch(:searcher) { searcher }
|
35
|
+
.new(scope: scope.resolve)
|
36
|
+
.search(params: params)
|
37
|
+
end
|
38
|
+
|
39
|
+
# Param manipulation based on User should be done here
|
40
|
+
def setup_index(**options)
|
41
|
+
options
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_support/concern'
|
4
|
+
require 'active_support/core_ext/string/inflections'
|
5
|
+
|
6
|
+
module SnFoil
|
7
|
+
module Contexts
|
8
|
+
module SetupContextConcern
|
9
|
+
extend ActiveSupport::Concern
|
10
|
+
|
11
|
+
class_methods do
|
12
|
+
attr_reader :i_model, :i_policy
|
13
|
+
|
14
|
+
def model(klass = nil)
|
15
|
+
@i_model = klass
|
16
|
+
end
|
17
|
+
|
18
|
+
def policy(klass = nil)
|
19
|
+
@i_policy = klass
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def model
|
24
|
+
self.class.i_model
|
25
|
+
end
|
26
|
+
|
27
|
+
def policy
|
28
|
+
self.class.i_policy
|
29
|
+
end
|
30
|
+
|
31
|
+
attr_reader :user
|
32
|
+
def initialize(user = nil)
|
33
|
+
@user = user
|
34
|
+
end
|
35
|
+
|
36
|
+
def authorize(object, action, **options)
|
37
|
+
return unless user # Add logging
|
38
|
+
|
39
|
+
lookup_policy(object, options).send(action)
|
40
|
+
end
|
41
|
+
|
42
|
+
def scope(object_class = nil, **options)
|
43
|
+
object_class ||= model
|
44
|
+
policy_name = lookup_policy(object_class, options).class.name
|
45
|
+
"#{policy_name}::Scope".safe_constantize.new(wrap_object(object_class), user)
|
46
|
+
end
|
47
|
+
|
48
|
+
def wrap_object(object)
|
49
|
+
return object unless adapter
|
50
|
+
|
51
|
+
adapter.new(object)
|
52
|
+
end
|
53
|
+
|
54
|
+
def unwrap_object(object)
|
55
|
+
return object unless adapter
|
56
|
+
|
57
|
+
adapter?(object) ? object.__getobj__ : object
|
58
|
+
end
|
59
|
+
|
60
|
+
def adapter?(object)
|
61
|
+
return false unless adapter
|
62
|
+
|
63
|
+
object.instance_of? adapter
|
64
|
+
end
|
65
|
+
|
66
|
+
def adapter
|
67
|
+
@adapter ||= SnFoil.adapter
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
def lookup_policy(object, options)
|
73
|
+
return options[:policy].new(user, object) if options[:policy]
|
74
|
+
return policy.new(user, object) if policy
|
75
|
+
|
76
|
+
Pundit.policy!(user, object)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_support/concern'
|
4
|
+
require_relative './setup_context_concern'
|
5
|
+
|
6
|
+
module SnFoil
|
7
|
+
module Contexts
|
8
|
+
module ShowContextConcern
|
9
|
+
extend ActiveSupport::Concern
|
10
|
+
|
11
|
+
included do
|
12
|
+
include SetupContextConcern
|
13
|
+
end
|
14
|
+
|
15
|
+
class_methods do
|
16
|
+
def show(id:, user: nil, **options)
|
17
|
+
new(user).show(**options, id: id)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def setup_show_object(id: nil, object: nil, **options)
|
22
|
+
raise ArgumentError, 'one of the following keywords is required: id, object' unless id || object
|
23
|
+
|
24
|
+
options.merge! object: wrap_object(object || scope.resolve.find(id))
|
25
|
+
end
|
26
|
+
|
27
|
+
def show(**options)
|
28
|
+
options[:action] = :show
|
29
|
+
options = setup_show_object(**options)
|
30
|
+
authorize(options[:object], :show?, **options)
|
31
|
+
unwrap_object options[:object]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,144 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_support/concern'
|
4
|
+
require_relative './setup_context_concern'
|
5
|
+
require_relative './change_context_concern'
|
6
|
+
|
7
|
+
module SnFoil
|
8
|
+
module Contexts
|
9
|
+
module UpdateContextConcern # rubocop:disable Metrics/ModuleLength
|
10
|
+
extend ActiveSupport::Concern
|
11
|
+
|
12
|
+
included do
|
13
|
+
include SetupContextConcern
|
14
|
+
include ChangeContextConcern
|
15
|
+
end
|
16
|
+
|
17
|
+
class_methods do
|
18
|
+
attr_reader :i_before_update_hooks, :i_after_update_hooks, :i_after_update_success_hooks, :i_after_update_failure_hooks
|
19
|
+
def update(id:, params:, user: nil, **options)
|
20
|
+
new(user).update(**options, id: id, params: params)
|
21
|
+
end
|
22
|
+
|
23
|
+
def before_update(method = nil, **options, &block)
|
24
|
+
raise ArgumentError, '#on_update requires either a method name or a block' if method.nil? && block.nil?
|
25
|
+
|
26
|
+
(@i_before_update_hooks ||= []) << { method: method, block: block, if: options[:if], unless: options[:unless] }
|
27
|
+
end
|
28
|
+
|
29
|
+
def after_update(method = nil, **options, &block)
|
30
|
+
raise ArgumentError, '#after_update requires either a method name or a block' if method.nil? && block.nil?
|
31
|
+
|
32
|
+
(@i_after_update_hooks ||= []) << { method: method, block: block, if: options[:if], unless: options[:unless] }
|
33
|
+
end
|
34
|
+
|
35
|
+
def after_update_success(method = nil, **options, &block)
|
36
|
+
raise ArgumentError, '#after_update_success requires either a method name or a block' if method.nil? && block.nil?
|
37
|
+
|
38
|
+
(@i_after_update_success_hooks ||= []) << { method: method, block: block, if: options[:if], unless: options[:unless] }
|
39
|
+
end
|
40
|
+
|
41
|
+
def after_update_failure(method = nil, **options, &block)
|
42
|
+
raise ArgumentError, '#after_update_failure requires either a method name or a block' if method.nil? && block.nil?
|
43
|
+
|
44
|
+
(@i_after_update_failure_hooks ||= []) << { method: method, block: block, if: options[:if], unless: options[:unless] }
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def setup_update_object(params: {}, id: nil, object: nil, **options)
|
49
|
+
raise ArgumentError, 'one of the following keywords is required: id, object' unless id || object
|
50
|
+
|
51
|
+
object = wrap_object(object || scope.resolve.find(id))
|
52
|
+
authorize(object, :update?, **options)
|
53
|
+
object.attributes = params
|
54
|
+
options.merge! object: object
|
55
|
+
end
|
56
|
+
|
57
|
+
def update(**options)
|
58
|
+
options[:action] = :update
|
59
|
+
options = setup_change(setup_update(**options))
|
60
|
+
options = setup_update_object(**options)
|
61
|
+
authorize(options[:object], :update?, **options)
|
62
|
+
options = update_hooks(**options)
|
63
|
+
unwrap_object(options[:object])
|
64
|
+
end
|
65
|
+
|
66
|
+
def setup_update(**options)
|
67
|
+
options
|
68
|
+
end
|
69
|
+
|
70
|
+
def before_update(**options)
|
71
|
+
options
|
72
|
+
end
|
73
|
+
|
74
|
+
def after_update(**options)
|
75
|
+
options
|
76
|
+
end
|
77
|
+
|
78
|
+
def after_update_success(**options)
|
79
|
+
options
|
80
|
+
end
|
81
|
+
|
82
|
+
def after_update_failure(**options)
|
83
|
+
options
|
84
|
+
end
|
85
|
+
|
86
|
+
def before_update_hooks
|
87
|
+
self.class.i_before_update_hooks || []
|
88
|
+
end
|
89
|
+
|
90
|
+
def after_update_hooks
|
91
|
+
self.class.i_after_update_hooks || []
|
92
|
+
end
|
93
|
+
|
94
|
+
def after_update_success_hooks
|
95
|
+
self.class.i_after_update_success_hooks || []
|
96
|
+
end
|
97
|
+
|
98
|
+
def after_update_failure_hooks
|
99
|
+
self.class.i_after_update_failure_hooks || []
|
100
|
+
end
|
101
|
+
|
102
|
+
private
|
103
|
+
|
104
|
+
# This method is private to help protect the order of execution of hooks
|
105
|
+
def update_hooks(options)
|
106
|
+
options = before_update_save(options)
|
107
|
+
options = if options[:object].save
|
108
|
+
after_update_save_success(options)
|
109
|
+
else
|
110
|
+
after_update_save_failure(options)
|
111
|
+
end
|
112
|
+
after_update_save(options)
|
113
|
+
end
|
114
|
+
|
115
|
+
def before_update_save(options)
|
116
|
+
options = before_update(**options)
|
117
|
+
options = before_update_hooks.reduce(options) { |opts, hook| run_hook(hook, **opts) }
|
118
|
+
options = before_change(**options)
|
119
|
+
before_change_hooks.reduce(options) { |opts, hook| run_hook(hook, **opts) }
|
120
|
+
end
|
121
|
+
|
122
|
+
def after_update_save(options)
|
123
|
+
options = after_update(**options)
|
124
|
+
options = after_update_hooks.reduce(options) { |opts, hook| run_hook(hook, **opts) }
|
125
|
+
options = after_change(**options)
|
126
|
+
after_change_hooks.reduce(options) { |opts, hook| run_hook(hook, **opts) }
|
127
|
+
end
|
128
|
+
|
129
|
+
def after_update_save_success(options)
|
130
|
+
options = after_update_success(**options)
|
131
|
+
options = after_update_success_hooks.reduce(options) { |opts, hook| run_hook(hook, **opts) }
|
132
|
+
options = after_change_success(**options)
|
133
|
+
after_change_success_hooks.reduce(options) { |opts, hook| run_hook(hook, **opts) }
|
134
|
+
end
|
135
|
+
|
136
|
+
def after_update_save_failure(options)
|
137
|
+
options = after_update_failure(**options)
|
138
|
+
options = after_update_failure_hooks.reduce(options) { |opts, hook| run_hook(hook, **opts) }
|
139
|
+
options = after_change_failure(**options)
|
140
|
+
after_change_failure_hooks.reduce(options) { |opts, hook| run_hook(hook, **opts) }
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_support/concern'
|
4
|
+
|
5
|
+
module SnFoil
|
6
|
+
module Policy
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
attr_reader :record, :entity
|
10
|
+
def initialize(record, entity = nil)
|
11
|
+
@record = record
|
12
|
+
@entity = entity
|
13
|
+
end
|
14
|
+
|
15
|
+
def index?
|
16
|
+
false
|
17
|
+
end
|
18
|
+
|
19
|
+
def show?
|
20
|
+
false
|
21
|
+
end
|
22
|
+
|
23
|
+
def create?
|
24
|
+
false
|
25
|
+
end
|
26
|
+
|
27
|
+
def update?
|
28
|
+
false
|
29
|
+
end
|
30
|
+
|
31
|
+
def destroy?
|
32
|
+
false
|
33
|
+
end
|
34
|
+
|
35
|
+
class Scope
|
36
|
+
attr_reader :scope, :entity
|
37
|
+
|
38
|
+
def initialize(scope, entity = nil)
|
39
|
+
@entity = entity
|
40
|
+
@scope = scope
|
41
|
+
end
|
42
|
+
|
43
|
+
def resolve
|
44
|
+
scope.all
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|