snfoil 0.5.5
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/CODE_OF_CONDUCT.md +74 -0
- data/README.md +43 -0
- data/Rakefile +4 -0
- data/lib/sn_foil.rb +49 -0
- data/lib/sn_foil/adapters/orms/active_record.rb +36 -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.rb +43 -0
- data/lib/sn_foil/contexts/change_context.rb +100 -0
- data/lib/sn_foil/contexts/create_context.rb +167 -0
- data/lib/sn_foil/contexts/destroy_context.rb +161 -0
- data/lib/sn_foil/contexts/index_context.rb +64 -0
- data/lib/sn_foil/contexts/setup_context.rb +118 -0
- data/lib/sn_foil/contexts/show_context.rb +61 -0
- data/lib/sn_foil/contexts/update_context.rb +164 -0
- data/lib/sn_foil/policy.rb +54 -0
- data/lib/sn_foil/searcher.rb +104 -0
- data/lib/sn_foil/version.rb +5 -0
- metadata +203 -0
@@ -0,0 +1,161 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_support/concern'
|
4
|
+
require_relative './setup_context'
|
5
|
+
require_relative './change_context'
|
6
|
+
|
7
|
+
module SnFoil
|
8
|
+
module Contexts
|
9
|
+
module DestroyContext # rubocop:disable Metrics/ModuleLength
|
10
|
+
extend ActiveSupport::Concern
|
11
|
+
|
12
|
+
included do
|
13
|
+
include SetupContext
|
14
|
+
include ChangeContext
|
15
|
+
end
|
16
|
+
|
17
|
+
class_methods do
|
18
|
+
attr_reader :i_setup_destroy_hooks, :i_before_destroy_hooks, :i_after_destroy_hooks,
|
19
|
+
:i_after_destroy_success_hooks, :i_after_destroy_failure_hooks
|
20
|
+
def destroy(id:, entity: nil, **options)
|
21
|
+
new(entity).destroy(**options, id: id)
|
22
|
+
end
|
23
|
+
|
24
|
+
def setup_destroy(method = nil, **options, &block)
|
25
|
+
raise ArgumentError, '#setup_destroy requires either a method name or a block' if method.nil? && block.nil?
|
26
|
+
|
27
|
+
(@i_setup_destroy_hooks ||= []) << { method: method, block: block, if: options[:if], unless: options[:unless] }
|
28
|
+
end
|
29
|
+
|
30
|
+
def before_destroy(method = nil, **options, &block)
|
31
|
+
raise ArgumentError, '#before_destroy requires either a method name or a block' if method.nil? && block.nil?
|
32
|
+
|
33
|
+
(@i_before_destroy_hooks ||= []) << { method: method, block: block, if: options[:if], unless: options[:unless] }
|
34
|
+
end
|
35
|
+
|
36
|
+
def after_destroy(method = nil, **options, &block)
|
37
|
+
raise ArgumentError, '#after_destroy requires either a method name or a block' if method.nil? && block.nil?
|
38
|
+
|
39
|
+
(@i_after_destroy_hooks ||= []) << { method: method, block: block, if: options[:if], unless: options[:unless] }
|
40
|
+
end
|
41
|
+
|
42
|
+
def after_destroy_success(method = nil, **options, &block)
|
43
|
+
raise ArgumentError, '#after_destroy_success requires either a method name or a block' if method.nil? && block.nil?
|
44
|
+
|
45
|
+
(@i_after_destroy_success_hooks ||= []) << { method: method, block: block, if: options[:if], unless: options[:unless] }
|
46
|
+
end
|
47
|
+
|
48
|
+
def after_destroy_failure(method = nil, **options, &block)
|
49
|
+
raise ArgumentError, '#after_destroy_failure requires either a method name or a block' if method.nil? && block.nil?
|
50
|
+
|
51
|
+
(@i_after_destroy_failure_hooks ||= []) << { method: method, block: block, if: options[:if], unless: options[:unless] }
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def setup_destroy_object(id: nil, object: nil, **options)
|
56
|
+
raise ArgumentError, 'one of the following keywords is required: id, object' unless id || object
|
57
|
+
|
58
|
+
options.merge! object: wrap_object(object || scope.resolve.find(id))
|
59
|
+
end
|
60
|
+
|
61
|
+
def destroy(**options)
|
62
|
+
options[:action] = :destroy
|
63
|
+
options = before_setup_destroy_object(**options)
|
64
|
+
options = setup_destroy_object(**options)
|
65
|
+
authorize(options[:object], :destroy?, **options)
|
66
|
+
options = destroy_hooks(**options)
|
67
|
+
unwrap_object(options[:object])
|
68
|
+
end
|
69
|
+
|
70
|
+
def setup_destroy(**options)
|
71
|
+
options
|
72
|
+
end
|
73
|
+
|
74
|
+
def before_destroy(**options)
|
75
|
+
options
|
76
|
+
end
|
77
|
+
|
78
|
+
def after_destroy(**options)
|
79
|
+
options
|
80
|
+
end
|
81
|
+
|
82
|
+
def after_destroy_success(**options)
|
83
|
+
options
|
84
|
+
end
|
85
|
+
|
86
|
+
def after_destroy_failure(**options)
|
87
|
+
options
|
88
|
+
end
|
89
|
+
|
90
|
+
def setup_destroy_hooks
|
91
|
+
self.class.i_setup_destroy_hooks || []
|
92
|
+
end
|
93
|
+
|
94
|
+
def before_destroy_hooks
|
95
|
+
self.class.i_before_destroy_hooks || []
|
96
|
+
end
|
97
|
+
|
98
|
+
def after_destroy_hooks
|
99
|
+
self.class.i_after_destroy_hooks || []
|
100
|
+
end
|
101
|
+
|
102
|
+
def after_destroy_success_hooks
|
103
|
+
self.class.i_after_destroy_success_hooks || []
|
104
|
+
end
|
105
|
+
|
106
|
+
def after_destroy_failure_hooks
|
107
|
+
self.class.i_after_destroy_failure_hooks || []
|
108
|
+
end
|
109
|
+
|
110
|
+
private
|
111
|
+
|
112
|
+
def before_setup_destroy_object(**options)
|
113
|
+
options = setup_destroy(**options)
|
114
|
+
options = setup_destroy_hooks.reduce(options) { |opts, hook| run_hook(hook, opts) }
|
115
|
+
options = setup_change(**options)
|
116
|
+
options = setup_change_hooks.reduce(options) { |opts, hook| run_hook(hook, opts) }
|
117
|
+
options = setup(**options)
|
118
|
+
setup_hooks.reduce(options) { |opts, hook| run_hook(hook, opts) }
|
119
|
+
end
|
120
|
+
|
121
|
+
# This method is private to help protect the order of execution of hooks
|
122
|
+
def destroy_hooks(options)
|
123
|
+
options = before_destroy_save(options)
|
124
|
+
options = if options[:object].destroy
|
125
|
+
after_destroy_save_success(options)
|
126
|
+
else
|
127
|
+
after_destroy_save_failure(options)
|
128
|
+
end
|
129
|
+
after_destroy_save(options)
|
130
|
+
end
|
131
|
+
|
132
|
+
def before_destroy_save(options)
|
133
|
+
options = before_destroy(**options)
|
134
|
+
options = before_destroy_hooks.reduce(options) { |opts, hook| run_hook(hook, **opts) }
|
135
|
+
options = before_change(**options)
|
136
|
+
before_change_hooks.reduce(options) { |opts, hook| run_hook(hook, **opts) }
|
137
|
+
end
|
138
|
+
|
139
|
+
def after_destroy_save(options)
|
140
|
+
options = after_destroy(**options)
|
141
|
+
options = after_destroy_hooks.reduce(options) { |opts, hook| run_hook(hook, **opts) }
|
142
|
+
options = after_change(**options)
|
143
|
+
after_change_hooks.reduce(options) { |opts, hook| run_hook(hook, **opts) }
|
144
|
+
end
|
145
|
+
|
146
|
+
def after_destroy_save_success(options)
|
147
|
+
options = after_destroy_success(**options)
|
148
|
+
options = after_destroy_success_hooks.reduce(options) { |opts, hook| run_hook(hook, **opts) }
|
149
|
+
options = after_change_success(**options)
|
150
|
+
after_change_success_hooks.reduce(options) { |opts, hook| run_hook(hook, **opts) }
|
151
|
+
end
|
152
|
+
|
153
|
+
def after_destroy_save_failure(options)
|
154
|
+
options = after_destroy_failure(**options)
|
155
|
+
options = after_destroy_failure_hooks.reduce(options) { |opts, hook| run_hook(hook, **opts) }
|
156
|
+
options = after_change_failure(**options)
|
157
|
+
after_change_failure_hooks.reduce(options) { |opts, hook| run_hook(hook, **opts) }
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_support/concern'
|
4
|
+
require_relative './change_context'
|
5
|
+
|
6
|
+
module SnFoil
|
7
|
+
module Contexts
|
8
|
+
module IndexContext
|
9
|
+
extend ActiveSupport::Concern
|
10
|
+
|
11
|
+
included do
|
12
|
+
include SetupContext
|
13
|
+
end
|
14
|
+
|
15
|
+
class_methods do
|
16
|
+
attr_reader :i_searcher, :i_setup_index_hooks
|
17
|
+
|
18
|
+
def index(params: {}, entity: nil, **options)
|
19
|
+
new(entity).index(**options, params: params)
|
20
|
+
end
|
21
|
+
|
22
|
+
def searcher(klass = nil)
|
23
|
+
@i_searcher = klass
|
24
|
+
end
|
25
|
+
|
26
|
+
def setup_index(method = nil, **options, &block)
|
27
|
+
raise ArgumentError, '#setup_index requires either a method name or a block' if method.nil? && block.nil?
|
28
|
+
|
29
|
+
(@i_setup_index_hooks ||= []) << { method: method, block: block, if: options[:if], unless: options[:unless] }
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def searcher
|
34
|
+
self.class.i_searcher
|
35
|
+
end
|
36
|
+
|
37
|
+
def setup_index_hooks
|
38
|
+
self.class.i_setup_index_hooks || []
|
39
|
+
end
|
40
|
+
|
41
|
+
def index(**options)
|
42
|
+
options[:action] = :index
|
43
|
+
options = before_setup_index(**options)
|
44
|
+
authorize(nil, :index?, **options)
|
45
|
+
options.fetch(:searcher) { searcher }
|
46
|
+
.new(scope: scope.resolve)
|
47
|
+
.search(options.fetch(:params) { {} })
|
48
|
+
end
|
49
|
+
|
50
|
+
def setup_index(**options)
|
51
|
+
options
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def before_setup_index(**options)
|
57
|
+
options = setup_index(**options)
|
58
|
+
options = setup_index_hooks.reduce(options) { |opts, hook| run_hook(hook, opts) }
|
59
|
+
options = setup(**options)
|
60
|
+
setup_hooks.reduce(options) { |opts, hook| run_hook(hook, opts) }
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,118 @@
|
|
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 SetupContext
|
9
|
+
extend ActiveSupport::Concern
|
10
|
+
|
11
|
+
class_methods do
|
12
|
+
attr_reader :i_model, :i_policy, :i_setup_hooks
|
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
|
+
|
22
|
+
def setup(method = nil, **options, &block)
|
23
|
+
raise ArgumentError, '#setup requires either a method name or a block' if method.nil? && block.nil?
|
24
|
+
|
25
|
+
(@i_setup_hooks ||= []) << { method: method, block: block, if: options[:if], unless: options[:unless] }
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def model
|
30
|
+
self.class.i_model
|
31
|
+
end
|
32
|
+
|
33
|
+
def policy
|
34
|
+
self.class.i_policy
|
35
|
+
end
|
36
|
+
|
37
|
+
def setup(**options)
|
38
|
+
options
|
39
|
+
end
|
40
|
+
|
41
|
+
def setup_hooks
|
42
|
+
self.class.i_setup_hooks || []
|
43
|
+
end
|
44
|
+
|
45
|
+
attr_reader :entity
|
46
|
+
def initialize(entity = nil)
|
47
|
+
@entity = entity
|
48
|
+
end
|
49
|
+
|
50
|
+
def authorize(object, action, **options)
|
51
|
+
return unless entity # Add logging
|
52
|
+
|
53
|
+
policy = lookup_policy(object, options)
|
54
|
+
raise Pundit::NotAuthorizedError, query: action, record: object, policy: policy unless policy.public_send(action)
|
55
|
+
|
56
|
+
true
|
57
|
+
end
|
58
|
+
|
59
|
+
def scope(object_class = nil, **options)
|
60
|
+
object_class ||= model
|
61
|
+
policy_name = lookup_policy(object_class, options).class.name
|
62
|
+
"#{policy_name}::Scope".safe_constantize.new(wrap_object(object_class), entity)
|
63
|
+
end
|
64
|
+
|
65
|
+
def wrap_object(object)
|
66
|
+
return object unless adapter
|
67
|
+
|
68
|
+
adapter.new(object)
|
69
|
+
end
|
70
|
+
|
71
|
+
def unwrap_object(object)
|
72
|
+
return object unless adapter
|
73
|
+
|
74
|
+
adapter?(object) ? object.__getobj__ : object
|
75
|
+
end
|
76
|
+
|
77
|
+
def adapter?(object)
|
78
|
+
return false unless adapter
|
79
|
+
|
80
|
+
object.instance_of? adapter
|
81
|
+
end
|
82
|
+
|
83
|
+
def adapter
|
84
|
+
@adapter ||= SnFoil.adapter
|
85
|
+
end
|
86
|
+
|
87
|
+
def run_hook(hook, **options)
|
88
|
+
return options unless hook_valid?(hook, **options)
|
89
|
+
|
90
|
+
return send(hook[:method], **options) if hook[:method]
|
91
|
+
|
92
|
+
instance_exec options, &hook[:block]
|
93
|
+
end
|
94
|
+
|
95
|
+
def hook_valid?(hook, **options)
|
96
|
+
return false if !hook[:if].nil? && hook[:if].call(options) == false
|
97
|
+
return false if !hook[:unless].nil? && hook[:unless].call(options) == true
|
98
|
+
|
99
|
+
true
|
100
|
+
end
|
101
|
+
|
102
|
+
private
|
103
|
+
|
104
|
+
def lookup_policy(object, options)
|
105
|
+
lookup = if options[:policy]
|
106
|
+
options[:policy].new(entity, object)
|
107
|
+
elsif policy
|
108
|
+
policy.new(entity, object)
|
109
|
+
else
|
110
|
+
Pundit.policy!(entity, object)
|
111
|
+
end
|
112
|
+
|
113
|
+
lookup.options = options if lookup.respond_to? :options=
|
114
|
+
lookup
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_support/concern'
|
4
|
+
require_relative './setup_context'
|
5
|
+
|
6
|
+
module SnFoil
|
7
|
+
module Contexts
|
8
|
+
module ShowContext
|
9
|
+
extend ActiveSupport::Concern
|
10
|
+
|
11
|
+
included do
|
12
|
+
include SetupContext
|
13
|
+
end
|
14
|
+
|
15
|
+
class_methods do
|
16
|
+
attr_reader :i_setup_show_hooks
|
17
|
+
|
18
|
+
def show(id:, entity: nil, **options)
|
19
|
+
new(entity).show(**options, id: id)
|
20
|
+
end
|
21
|
+
|
22
|
+
def setup_show(method = nil, **options, &block)
|
23
|
+
raise ArgumentError, '#setup_show requires either a method name or a block' if method.nil? && block.nil?
|
24
|
+
|
25
|
+
(@i_setup_show_hooks ||= []) << { method: method, block: block, if: options[:if], unless: options[:unless] }
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def setup_show_object(id: nil, object: nil, **options)
|
30
|
+
raise ArgumentError, 'one of the following keywords is required: id, object' unless id || object
|
31
|
+
|
32
|
+
options.merge! object: wrap_object(object || scope.resolve.find(id))
|
33
|
+
end
|
34
|
+
|
35
|
+
def setup_show_hooks
|
36
|
+
self.class.i_setup_show_hooks || []
|
37
|
+
end
|
38
|
+
|
39
|
+
def show(**options)
|
40
|
+
options[:action] = :show
|
41
|
+
options = before_setup_show(**options)
|
42
|
+
options = setup_show_object(**options)
|
43
|
+
authorize(options[:object], :show?, **options)
|
44
|
+
unwrap_object options[:object]
|
45
|
+
end
|
46
|
+
|
47
|
+
def setup_show(**options)
|
48
|
+
options
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def before_setup_show(**options)
|
54
|
+
options = setup_show(**options)
|
55
|
+
options = setup_show_hooks.reduce(options) { |opts, hook| run_hook(hook, opts) }
|
56
|
+
options = setup(**options)
|
57
|
+
setup_hooks.reduce(options) { |opts, hook| run_hook(hook, opts) }
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,164 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_support/concern'
|
4
|
+
require_relative './setup_context'
|
5
|
+
require_relative './change_context'
|
6
|
+
|
7
|
+
module SnFoil
|
8
|
+
module Contexts
|
9
|
+
module UpdateContext # rubocop:disable Metrics/ModuleLength
|
10
|
+
extend ActiveSupport::Concern
|
11
|
+
|
12
|
+
included do
|
13
|
+
include SetupContext
|
14
|
+
include ChangeContext
|
15
|
+
end
|
16
|
+
|
17
|
+
class_methods do
|
18
|
+
attr_reader :i_setup_update_hooks, :i_before_update_hooks, :i_after_update_hooks,
|
19
|
+
:i_after_update_success_hooks, :i_after_update_failure_hooks
|
20
|
+
def update(id:, params:, entity: nil, **options)
|
21
|
+
new(entity).update(**options, id: id, params: params)
|
22
|
+
end
|
23
|
+
|
24
|
+
def setup_update(method = nil, **options, &block)
|
25
|
+
raise ArgumentError, '#setup_update requires either a method name or a block' if method.nil? && block.nil?
|
26
|
+
|
27
|
+
(@i_setup_update_hooks ||= []) << { method: method, block: block, if: options[:if], unless: options[:unless] }
|
28
|
+
end
|
29
|
+
|
30
|
+
def before_update(method = nil, **options, &block)
|
31
|
+
raise ArgumentError, '#before_update requires either a method name or a block' if method.nil? && block.nil?
|
32
|
+
|
33
|
+
(@i_before_update_hooks ||= []) << { method: method, block: block, if: options[:if], unless: options[:unless] }
|
34
|
+
end
|
35
|
+
|
36
|
+
def after_update(method = nil, **options, &block)
|
37
|
+
raise ArgumentError, '#after_update requires either a method name or a block' if method.nil? && block.nil?
|
38
|
+
|
39
|
+
(@i_after_update_hooks ||= []) << { method: method, block: block, if: options[:if], unless: options[:unless] }
|
40
|
+
end
|
41
|
+
|
42
|
+
def after_update_success(method = nil, **options, &block)
|
43
|
+
raise ArgumentError, '#after_update_success requires either a method name or a block' if method.nil? && block.nil?
|
44
|
+
|
45
|
+
(@i_after_update_success_hooks ||= []) << { method: method, block: block, if: options[:if], unless: options[:unless] }
|
46
|
+
end
|
47
|
+
|
48
|
+
def after_update_failure(method = nil, **options, &block)
|
49
|
+
raise ArgumentError, '#after_update_failure requires either a method name or a block' if method.nil? && block.nil?
|
50
|
+
|
51
|
+
(@i_after_update_failure_hooks ||= []) << { method: method, block: block, if: options[:if], unless: options[:unless] }
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def setup_update_object(params: {}, id: nil, object: nil, **options)
|
56
|
+
raise ArgumentError, 'one of the following keywords is required: id, object' unless id || object
|
57
|
+
|
58
|
+
object = wrap_object(object || scope.resolve.find(id))
|
59
|
+
authorize(object, :update?, **options)
|
60
|
+
object.attributes = params
|
61
|
+
options.merge! object: object
|
62
|
+
end
|
63
|
+
|
64
|
+
def update(**options)
|
65
|
+
options[:action] = :update
|
66
|
+
options = before_setup_update_object(**options)
|
67
|
+
options = setup_update_object(**options)
|
68
|
+
authorize(options[:object], :update?, **options)
|
69
|
+
options = update_hooks(**options)
|
70
|
+
unwrap_object(options[:object])
|
71
|
+
end
|
72
|
+
|
73
|
+
def setup_update(**options)
|
74
|
+
options
|
75
|
+
end
|
76
|
+
|
77
|
+
def before_update(**options)
|
78
|
+
options
|
79
|
+
end
|
80
|
+
|
81
|
+
def after_update(**options)
|
82
|
+
options
|
83
|
+
end
|
84
|
+
|
85
|
+
def after_update_success(**options)
|
86
|
+
options
|
87
|
+
end
|
88
|
+
|
89
|
+
def after_update_failure(**options)
|
90
|
+
options
|
91
|
+
end
|
92
|
+
|
93
|
+
def setup_update_hooks
|
94
|
+
self.class.i_setup_update_hooks || []
|
95
|
+
end
|
96
|
+
|
97
|
+
def before_update_hooks
|
98
|
+
self.class.i_before_update_hooks || []
|
99
|
+
end
|
100
|
+
|
101
|
+
def after_update_hooks
|
102
|
+
self.class.i_after_update_hooks || []
|
103
|
+
end
|
104
|
+
|
105
|
+
def after_update_success_hooks
|
106
|
+
self.class.i_after_update_success_hooks || []
|
107
|
+
end
|
108
|
+
|
109
|
+
def after_update_failure_hooks
|
110
|
+
self.class.i_after_update_failure_hooks || []
|
111
|
+
end
|
112
|
+
|
113
|
+
private
|
114
|
+
|
115
|
+
def before_setup_update_object(**options)
|
116
|
+
options = setup_update(**options)
|
117
|
+
options = setup_update_hooks.reduce(options) { |opts, hook| run_hook(hook, opts) }
|
118
|
+
options = setup_change(**options)
|
119
|
+
options = setup_change_hooks.reduce(options) { |opts, hook| run_hook(hook, opts) }
|
120
|
+
options = setup(**options)
|
121
|
+
setup_hooks.reduce(options) { |opts, hook| run_hook(hook, opts) }
|
122
|
+
end
|
123
|
+
|
124
|
+
# This method is private to help protect the order of execution of hooks
|
125
|
+
def update_hooks(options)
|
126
|
+
options = before_update_save(options)
|
127
|
+
options = if options[:object].save
|
128
|
+
after_update_save_success(options)
|
129
|
+
else
|
130
|
+
after_update_save_failure(options)
|
131
|
+
end
|
132
|
+
after_update_save(options)
|
133
|
+
end
|
134
|
+
|
135
|
+
def before_update_save(options)
|
136
|
+
options = before_update(**options)
|
137
|
+
options = before_update_hooks.reduce(options) { |opts, hook| run_hook(hook, **opts) }
|
138
|
+
options = before_change(**options)
|
139
|
+
before_change_hooks.reduce(options) { |opts, hook| run_hook(hook, **opts) }
|
140
|
+
end
|
141
|
+
|
142
|
+
def after_update_save(options)
|
143
|
+
options = after_update(**options)
|
144
|
+
options = after_update_hooks.reduce(options) { |opts, hook| run_hook(hook, **opts) }
|
145
|
+
options = after_change(**options)
|
146
|
+
after_change_hooks.reduce(options) { |opts, hook| run_hook(hook, **opts) }
|
147
|
+
end
|
148
|
+
|
149
|
+
def after_update_save_success(options)
|
150
|
+
options = after_update_success(**options)
|
151
|
+
options = after_update_success_hooks.reduce(options) { |opts, hook| run_hook(hook, **opts) }
|
152
|
+
options = after_change_success(**options)
|
153
|
+
after_change_success_hooks.reduce(options) { |opts, hook| run_hook(hook, **opts) }
|
154
|
+
end
|
155
|
+
|
156
|
+
def after_update_save_failure(options)
|
157
|
+
options = after_update_failure(**options)
|
158
|
+
options = after_update_failure_hooks.reduce(options) { |opts, hook| run_hook(hook, **opts) }
|
159
|
+
options = after_change_failure(**options)
|
160
|
+
after_change_failure_hooks.reduce(options) { |opts, hook| run_hook(hook, **opts) }
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|