snfoil-context 0.0.2 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 192d032e33ddaa32cb1ead86d97947a03eaee657af7c26a44effe1c47eeefe7a
4
- data.tar.gz: e181f4ac51ccc95c0e50377b3186679b5f313824f4a650f7dbe80efb69e4f68b
3
+ metadata.gz: a9996ed485265b54e92858f7471b6ed2ccfc3970b6ab7bed338f0b3ab729d240
4
+ data.tar.gz: 2427755a9b61cf1fad8ddc48eaa6e5c1e7da651b6c6b8f760f6594e1a973c471
5
5
  SHA512:
6
- metadata.gz: 41bbbdce248d49d94e646a2d446ff99ce9fa195dc235024cd85030d8f4664c2f0ddb4b1b42ba906df50ce71d330425bc5d582a8783be10603f9dc94745b10871
7
- data.tar.gz: d0cbddc6b61b6bccae81d5a6b2db8930cada0f9f9729595aa1203252440f93b0d8e3fc9ea630dd2790eba7e69d17242390e76766d6e5b36dc35ef87fc4c3c5c5
6
+ metadata.gz: d8e89dc09f5d1a1ca531487b04e9392c5323330c232d9f3a72946c4130ead35425451a2bec1d7a522702c414cdd7cb08ea85447f60d89a72a948fda27f17d667
7
+ data.tar.gz: a1f773ecb81a5a4ee2ffce81b3bf350c49e18078ba465f35e4ed824b01587dd5a9d5fc4897131a1c4b93fe9675655c086d489c9d99e0c05615af139f4644d13f
data/.fasterer.yml ADDED
@@ -0,0 +1,22 @@
1
+ speedups:
2
+ rescue_vs_respond_to: true
3
+ module_eval: true
4
+ shuffle_first_vs_sample: true
5
+ for_loop_vs_each: true
6
+ each_with_index_vs_while: false
7
+ map_flatten_vs_flat_map: true
8
+ reverse_each_vs_reverse_each: true
9
+ select_first_vs_detect: true
10
+ sort_vs_sort_by: true
11
+ fetch_with_argument_vs_block: true
12
+ keys_each_vs_each_key: true
13
+ hash_merge_bang_vs_hash_brackets: true
14
+ block_vs_symbol_to_proc: true
15
+ proc_call_vs_yield: true
16
+ gsub_vs_tr: true
17
+ select_last_vs_reverse_detect: true
18
+ getter_vs_attr_reader: true
19
+ setter_vs_attr_writer: true
20
+
21
+ exclude_paths:
22
+ - 'vendor/**/*.rb'
@@ -1,5 +1,5 @@
1
1
  name: build
2
- on:
2
+ on:
3
3
  push:
4
4
  branches: [ main ]
5
5
  pull_request:
@@ -11,7 +11,7 @@ jobs:
11
11
 
12
12
  strategy:
13
13
  matrix:
14
- ruby-version: [2.7, 2.6, 2.5]
14
+ ruby-version: [2.7, 2.6, 2.5, '3.0']
15
15
 
16
16
  steps:
17
17
  - uses: actions/checkout@v2
@@ -43,4 +43,7 @@ jobs:
43
43
  run: bundle install
44
44
  - name: Run rubocop
45
45
  run: bundle exec rubocop
46
-
46
+ - name: Run fasterer
47
+ run: bundle exec fasterer
48
+ - name: Run bundle audit
49
+ run: bundle exec bundle audit check --update
data/.rubocop.yml CHANGED
@@ -24,6 +24,7 @@ Lint/EmptyClass:
24
24
  Metrics/BlockLength:
25
25
  Exclude:
26
26
  - spec/**/*_spec.rb
27
+ - snfoil-context.gemspec
27
28
 
28
29
  # ================ RSPEC ================
29
30
  RSpec/FilePath:
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  ![build](https://github.com/limited-effort/snfoil-context/actions/workflows/main.yml/badge.svg) [![maintainability](https://api.codeclimate.com/v1/badges/6a7a2f643707c17cb879/maintainability)](https://codeclimate.com/github/limited-effort/snfoil-context/maintainability)
4
4
 
5
- SnFoil Contexts are a simple way to insure a workflow pipeline can be easily established end extended. It helps by creating workflow, allowing additional in steps at specific intervals, and reacting to a success or failure, you should find your code being more maintainable and testable.
5
+ SnFoil Contexts are a simple way to ensure a workflow pipeline can be easily established end extended. It helps by creating a workflow, allowing additional steps at specific intervals, and reacting to success or failure, you should find your code being more maintainable and testable.
6
6
 
7
7
  ## Installation
8
8
 
@@ -15,7 +15,47 @@ gem 'snfoil-context'
15
15
  ## Usage
16
16
  While contexts are powerful, they aren't a magic bullet. Each function should strive to only contain a single purpose. This also has the added benefit of outlining some basic tests - if it is in a function it should have a related test.
17
17
 
18
- ### Action
18
+
19
+ ### Quickstart Example
20
+
21
+ ```ruby
22
+ require 'snfoil/context'
23
+
24
+ class TokenContext
25
+ include SnFoil::Context
26
+
27
+ action(:create) { |options| options[:object].save }
28
+ action(:expire) { |options| options[:object].update(expired_at: Time.current) }
29
+
30
+ # inject created_by
31
+ setup_create { |options| options[:params][:created_by] = entity }
32
+
33
+ # initialize token
34
+ before_create do |options|
35
+ options[:object] = Token.create(options[:params])
36
+ options
37
+ end
38
+
39
+ # send token email
40
+ after_create_success { |options| TokenMailer.new(token: option[:object]) }
41
+
42
+ # log expiration error
43
+ after_expire_failure { |options| ErrorLogger.notify(error: options[:object].errors) }
44
+ end
45
+ ```
46
+
47
+
48
+ ### Initialize
49
+
50
+ When you `new` up a SnFoil Context you should provide the entity running the actions. This will usually be a user but you can pass in anything. This will be accessible from within the context as `entity`.
51
+
52
+ ```ruby
53
+ TokenContext.new(current_user)
54
+ ```
55
+
56
+ ### Actions
57
+ Actions are a group of hookable intervals that create a workflow around a single primary function.
58
+
19
59
  To start you will need to define an action.
20
60
 
21
61
  Arguments:
@@ -30,18 +70,32 @@ require 'snfoil/context'
30
70
  class TokenContext
31
71
  include SnFoil::Context
32
72
 
33
- action :expire { |options| options[:object].update(expired_at: Time.current) }
73
+ ...
74
+
75
+ action(:expire) { |options| options[:object].update(expired_at: Time.current) }
34
76
  end
35
77
  ```
36
78
 
37
- This will generate the methods and hooks of the pipeline. In this example the following get made:
79
+ This will generate the intervals of the pipeline. In this example the following get made:
38
80
  * setup_expire
39
81
  * before_expire
40
82
  * after_expire_success
41
83
  * after_expire_failure
42
84
  * after_expire
43
85
 
44
- If you want to reuse the primary action or just prefer methods, you can pass in the method name you would like to call, rather than providing a block. If a method name and a block is provided, the block is ignored.
86
+ Now you can trigger the workflow by calling the action as a method on an instance of the context.
87
+
88
+ ```ruby
89
+ class TokenContext
90
+ include SnFoil::Context
91
+
92
+ action(:expire) { |options| options[:object].update(expired_at: Time.current) }
93
+ end
94
+
95
+ TokenContext.new(current_user).expire(object: current_token)
96
+ ```
97
+
98
+ If you want to reuse the primary action or just prefer methods, you can pass in the method name you would like to call, rather than providing a block. If a method name and a block are provided, the block is ignored.
45
99
 
46
100
 
47
101
  ```ruby
@@ -59,10 +113,10 @@ class TokenContext
59
113
  end
60
114
  ```
61
115
 
62
- #### Primary Actions
63
- The primary action is the function that determine whether or not the action is successful. To do this, the primary action must always return a truthy value if the action was successful, or a falsey one if it failed.
116
+ #### Primary Function
117
+ The primary function is the function that determines whether or not the action is successful. To do this, the primary function must always return a truthy value if the action was successful, or a falsey one if it failed.
64
118
 
65
- The primary action is passed one argument which is the return value of the closest preceeding interval function.
119
+ The primary function is passed one argument which is the return value of the closest preceding interval function.
66
120
 
67
121
  ```ruby
68
122
  # lib/contexts/token_context
@@ -85,67 +139,67 @@ class TokenContext
85
139
  end
86
140
  ```
87
141
 
88
- #### Intervals
89
- The following are the intervals SnFoil Contexts sets up in the order they occur. The suggested uses are just very simply examples. You can chain contexts to setup very complex interactions in a very easy to manage workflow.
142
+ #### Action Intervals
143
+ The following are the intervals SnFoil Contexts set up in the order they occur. The suggested uses are just very simple examples. You can chain contexts to setup very complex interactions in a very easy-to-manage workflow.
90
144
 
91
145
  <table>
92
- <thead>
93
- <th>Name</th>
94
- <th>Suggested Use</th>
95
- </thead>
96
- <tbody>
97
- <tr>
98
- <td>setup_&lt;action&gt;</td>
99
- <td>
100
- <div>* find or create a model</div>
101
- <div>* setup params needed later in the action</div>
102
- <div>* set scoping </div>
103
- </td>
104
- </tr>
105
- <tr>
106
- <td>before_&lt;action&gt;</td>
107
- <td>
108
- <div>* alter model or set attributes</div>
109
- </td>
110
- </tr>
111
- <tr>
112
- <td>primary action</td>
113
- <td>
114
- <div>* persist database changes</div>
115
- <div>* make primary network call</div>
116
- </td>
117
- </tr>
118
- <tr>
119
- <td>after_&lt;action&gt;_success</td>
120
- <td>
121
- <div>* setup additional relationships</div>
122
- <div>* success specific logging</div>
123
- </td>
124
- </tr>
125
- <tr>
126
- <td>after_&lt;action&gt;_failure</td>
127
- <td>
128
- <div>* cleanup failed remenants</div>
129
- <div>* call bug tracker</div>
130
- <div>* failure specific logging</div>
131
- </td>
132
- </tr>
133
- <tr>
134
- <td>after_&lt;action&gt;</td>
135
- <td>
136
- <div>* perform necessary required cleanup</div>
137
- <div>* log outcome</div>
138
- </td>
139
- </tr>
140
- </tbody>
146
+ <thead>
147
+ <th>Name</th>
148
+ <th>Suggested Use</th>
149
+ </thead>
150
+ <tbody>
151
+ <tr>
152
+ <td>setup_&lt;action&gt;</td>
153
+ <td>
154
+ <div>* find or create a model</div>
155
+ <div>* setup params needed later in the action</div>
156
+ <div>* set scoping </div>
157
+ </td>
158
+ </tr>
159
+ <tr>
160
+ <td>before_&lt;action&gt;</td>
161
+ <td>
162
+ <div>* alter model or set attributes</div>
163
+ </td>
164
+ </tr>
165
+ <tr>
166
+ <td>primary action</td>
167
+ <td>
168
+ <div>* persist database changes</div>
169
+ <div>* make primary network call</div>
170
+ </td>
171
+ </tr>
172
+ <tr>
173
+ <td>after_&lt;action&gt;_success</td>
174
+ <td>
175
+ <div>* setup additional relationships</div>
176
+ <div>* success specific logging</div>
177
+ </td>
178
+ </tr>
179
+ <tr>
180
+ <td>after_&lt;action&gt;_failure</td>
181
+ <td>
182
+ <div>* cleanup failed remenants</div>
183
+ <div>* call bug tracker</div>
184
+ <div>* failure specific logging</div>
185
+ </td>
186
+ </tr>
187
+ <tr>
188
+ <td>after_&lt;action&gt;</td>
189
+ <td>
190
+ <div>* perform necessary required cleanup</div>
191
+ <div>* log outcome</div>
192
+ </td>
193
+ </tr>
194
+ </tbody>
141
195
  <table>
142
196
 
143
197
 
144
198
  #### Hook and Method Design
145
199
 
146
- SnFoil Contexts try hard to not store variables longer than necessary. To facilitate this we have choosen to pass an object (we normally use a hash called options) to each hook and method, and the return from the hook or method is passed down the chain to the next hook or method.
200
+ SnFoil Contexts try hard to not store variables longer than necessary. To facilitate this we have chosen to pass an object (we normally use a hash called options) to each hook and method, and the return from the hook or method is passed down the chain to the next hook or method.
147
201
 
148
- The only method or block that does not get its value passwed down the chain is the primary action - which must always return a truthy value of whether or not the action was successful.
202
+ The only method or block that does not get its value passed down the chain is the primary action - which must always return a truthy value of whether or not the action was successful.
149
203
 
150
204
  #### Hooks
151
205
  Hooks make it very easy to compose multiple actions that need to occur in a specific order. You can have as many repeated hooks as you would like. This makes defining single responsibility hooks very simple, and they will get called in the order they are defined.
@@ -156,29 +210,29 @@ Hooks make it very easy to compose multiple actions that need to occur in a spec
156
210
  ```ruby
157
211
  # Call the webhooks for third party integrations
158
212
  after_expire_success do |options|
159
- call_webhook_for_model(options[:object])
160
- options
213
+ call_webhook_for_model(options[:object])
214
+ options
161
215
  end
162
216
 
163
217
  # Commit business logic to internal process
164
218
  after_expire_success do |options|
165
- finalize_business_logic(options[:object])
166
- options
219
+ finalize_business_logic(options[:object])
220
+ options
167
221
  end
168
222
 
169
223
  # notify error tracker
170
224
  after_expire_error do |options|
171
- notify_errors(options[:object].errors)
172
- options
225
+ notify_errors(options[:object].errors)
226
+ options
173
227
  end
174
228
  ```
175
229
 
176
230
  #### Methods
177
- Methods allow users to create inheritable actions that occur in a specific order. Methods will always run after their hook counterpart. Since these are inheritable, you can chain needed actions all the way through the parent heirarchy by using the `super` keyword.
231
+ Methods allow users to create inheritable actions that occur in a specific order. Methods will always run after their hook counterpart. Since these are inheritable, you can chain needed actions through the parent hierarchy by using the `super` keyword. These are very useful when you need to have something always happen at the end of an Interval.
178
232
 
179
233
  <strong>Important Note</strong> Methods <u>always</u> need to return the options hash at the end.
180
234
 
181
- <i>Author's opinion:</i> While simplier than hooks, they do not allow for as clean of a composition as hooks.
235
+ <i>Author's opinion:</i> While simpler than hooks, they do not allow for as clean of a composition as hooks.
182
236
 
183
237
  ##### Example
184
238
 
@@ -186,21 +240,21 @@ Methods allow users to create inheritable actions that occur in a specific order
186
240
  # Call the webhooks for third party integrations
187
241
  # Commit business logic to internal process
188
242
  def after_expire_success(**options)
189
- options = super
243
+ options = super
190
244
 
191
- call_webhook_for_model(options[:object])
192
- finalize_business_logic(options[:object])
245
+ call_webhook_for_model(options[:object])
246
+ finalize_business_logic(options[:object])
193
247
 
194
- options
248
+ options
195
249
  end
196
250
 
197
251
  # notify error tracker
198
252
  def after_expire_error(**options)
199
- options = super
253
+ options = super
200
254
 
201
- notify_errors(options[:object].errors)
255
+ notify_errors(options[:object].errors)
202
256
 
203
- options
257
+ options
204
258
  end
205
259
  ```
206
260
 
@@ -209,10 +263,10 @@ The original purpose of all of SnFoil was to ensure there was a good consistent
209
263
 
210
264
  These authorization hooks are always called twice. Once after `setup_<action>` and once after `before_<action>`
211
265
 
212
- The `authorize` method functions much like primary action except the first argument is usually the name of action you are authorizing.
266
+ The `authorize` method functions much like primary action except the first argument is usually the name of the action you are authorizing.
213
267
 
214
268
  Arguments:
215
- * `name` - The name of this action to be authorized. If ommited, all actions without a specific associated authorize will use this one..
269
+ * `name` - The name of this action to be authorized. If omitted, all actions without a specific associated authorize will use this
216
270
  * `with` - Keyword Param - The method name of the primary action. Either this or a block is required
217
271
  * `block` - Block - The block of the primary action. Either this or with is required
218
272
 
@@ -225,13 +279,13 @@ class TokenContext
225
279
 
226
280
  action :expire, with: :expire_token
227
281
 
228
- authorize :expire { |options| options[:entity].is_admin? }
282
+ authorize(:expire) { |_options| :entity.is_admin? }
229
283
 
230
284
  ...
231
285
  end
232
286
  ```
233
287
 
234
- You can also call authorize without an action name. This will have all action authorize with the provided method or block unless there is a more specific authorize action configured. Its probably easier explained with an example
288
+ You can also call authorize without an action name. This will have all action authorize with the provided method or block unless there is a more specific authorize action configured. It's probably easier explained with an example
235
289
 
236
290
 
237
291
  ```ruby
@@ -245,15 +299,44 @@ class TokenContext
245
299
  action :search, with: :query_tokens #=> will authorize by checking the entity is a user
246
300
  action :show, with: :find_token #=> will authorize by checking the entity is a user
247
301
 
248
- authorize :expire { |options| options[:entity].is_admin? }
249
- authorize { |options| options[:entity].is_user? }
302
+ authorize(:expire) { |_options| entity.is_admin? }
303
+ authorize { |_options| entity.is_user? }
250
304
 
251
305
  ...
252
306
  end
253
307
  ```
254
308
 
255
309
  #### Why before and after?
256
- Simply to make sure the entity it actually allowed access the primary target and is allowed to make the requested alterations/interactions.
310
+ Simply to make sure the entity is allowed access to the primary target and is allowed to make the requested alterations/interactions.
311
+
312
+ ### Intervals
313
+ There might be a situation where you don't need a before, after, success or failure, and just need a single name pipeline you can hook into. `interval` allows you to create a single action-like segment.
314
+
315
+ ```ruby
316
+ class TokenContext
317
+ include SnFoil::Context
318
+
319
+ interval :demo
320
+
321
+ demo do |options|
322
+ ... # Logic Here
323
+
324
+ options
325
+ end
326
+
327
+ demo do |options|
328
+ ... # Additional Steps here
329
+
330
+ options
331
+ end
332
+ end
333
+ ```
334
+
335
+ Just like for an action SnFoil allows you to define both hooks and a method. To run this interval you call it using the `run_interval` method.
336
+
337
+ ```ruby
338
+ TokenContext.new(entity).run_interval(:demo, **options)
339
+ ```
257
340
 
258
341
  ## Development
259
342
 
@@ -271,4 +354,4 @@ The gem is available as open source under the terms of the [Apache 2 License](ht
271
354
 
272
355
  ## Code of Conduct
273
356
 
274
- Everyone interacting in the Snfoil::Context project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/limited-effort/snfoil-context/blob/main/CODE_OF_CONDUCT.md).
357
+ Everyone interacting in the Snfoil::Context project's codebases, issue trackers, chat rooms, and mailing lists is expected to follow the [code of conduct](https://github.com/limited-effort/snfoil-context/blob/main/CODE_OF_CONDUCT.md).
@@ -28,15 +28,25 @@ module SnFoil
28
28
  extend ActiveSupport::Concern
29
29
 
30
30
  class_methods do
31
- attr_reader :i_authorizations
31
+ attr_accessor :snfoil_authorizations
32
32
 
33
33
  def authorize(action_name = nil, with: nil, &block)
34
- @i_authorizations ||= {}
34
+ @snfoil_authorizations ||= {}
35
35
  action_name = action_name&.to_sym
36
36
 
37
- raise SnFoil::Context::Error, "#{name} already has authorize defined for #{action_name || ':default'}" if @i_authorizations[action_name]
37
+ if @snfoil_authorizations[action_name]
38
+ raise SnFoil::Context::Error, "#{name} already has authorize defined for #{action_name || ':default'}"
39
+ end
38
40
 
39
- @i_authorizations[action_name] = { method: with, block: block }
41
+ @snfoil_authorizations[action_name] = { method: with, block: block }
42
+ end
43
+
44
+ def inherited(subclass)
45
+ super
46
+
47
+ instance_variables.grep(/@snfoil_.+/).each do |i|
48
+ subclass.instance_variable_set(i, instance_variable_get(i).dup)
49
+ end
40
50
  end
41
51
  end
42
52
 
@@ -47,8 +57,8 @@ module SnFoil
47
57
  end
48
58
 
49
59
  def authorize(name, **options)
50
- configured_call = self.class.i_authorizations&.fetch(name.to_sym, nil)
51
- configured_call ||= self.class.i_authorizations&.fetch(nil, nil)
60
+ configured_call = self.class.snfoil_authorizations&.fetch(name.to_sym, nil)
61
+ configured_call ||= self.class.snfoil_authorizations&.fetch(nil, nil)
52
62
 
53
63
  if configured_call
54
64
  run_hook(configured_call, **options)
@@ -65,12 +75,12 @@ module SnFoil
65
75
 
66
76
  return send(hook[:method], **options) if hook[:method]
67
77
 
68
- instance_exec options, &hook[:block]
78
+ instance_exec(**options, &hook[:block])
69
79
  end
70
80
 
71
81
  def hook_valid?(hook, **options)
72
- return false if !hook[:if].nil? && hook[:if].call(options) == false
73
- return false if !hook[:unless].nil? && hook[:unless].call(options) == true
82
+ return false if !hook[:if].nil? && hook[:if].call(**options) == false
83
+ return false if !hook[:unless].nil? && hook[:unless].call(**options) == true
74
84
 
75
85
  true
76
86
  end
@@ -16,6 +16,6 @@
16
16
 
17
17
  module SnFoil
18
18
  module Context
19
- VERSION = '0.0.2'
19
+ VERSION = '0.0.4'
20
20
  end
21
21
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Copyright 2021 Matthew Howes
3
+ # Copyright 2021 Matthew Howes, Cliff Campbell
4
4
 
5
5
  # Licensed under the Apache License, Version 2.0 (the "License");
6
6
  # you may not use this file except in compliance with the License.
@@ -35,20 +35,27 @@ module SnFoil
35
35
 
36
36
  class_methods do
37
37
  def action(name, with: nil, &block)
38
- raise SnFoil::Context::Error, "action #{name} already defined for #{self.name}" if (@defined_actions ||= []).include?(name)
38
+ raise SnFoil::Context::Error, "action #{name} already defined for #{self.name}" if (@snfoil_actions ||= []).include?(name)
39
39
 
40
- @defined_actions << name
41
- define_workflow_hooks(name)
40
+ @snfoil_actions << name
41
+ define_workflow(name)
42
42
  define_action_primary(name, with, block)
43
43
  end
44
- end
45
44
 
46
- def run_action_group(group_name, **options)
47
- hooks = self.class.instance_variable_get("@#{group_name}_hooks") || []
48
- options = hooks.reduce(options) { |opts, hook| run_hook(hook, opts) }
49
- options = send(group_name, **options) if respond_to?(group_name)
45
+ def interval(name)
46
+ define_singleton_methods(name)
47
+ define_instance_methods(name)
48
+ end
49
+
50
+ def intervals(*names)
51
+ names.each { |name| interval(name) }
52
+ end
53
+ end
50
54
 
51
- options
55
+ def run_interval(interval, **options)
56
+ hooks = self.class.instance_variable_get("@snfoil_#{interval}_hooks") || []
57
+ options = hooks.reduce(options) { |opts, hook| run_hook(hook, **opts) }
58
+ send(interval, **options)
52
59
  end
53
60
 
54
61
  private
@@ -56,38 +63,35 @@ module SnFoil
56
63
  # rubocop:disable reason: These are builder/mapping methods that are just too complex to simplify without
57
64
  # making them more complex. If anyone has a better way please let me know
58
65
  class_methods do # rubocop:disable Metrics/BlockLength
66
+ def define_workflow(name)
67
+ interval format('setup_%s', name)
68
+ interval format('before_%s', name)
69
+ interval format('after_%s_success', name)
70
+ interval format('after_%s_failure', name)
71
+ interval format('after_%s', name)
72
+ end
73
+
59
74
  def define_action_primary(name, method, block) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
60
- define_method(name) do |**options| # rubocop:disable Metrics/MethodLength
61
- options[:action] = name.to_sym
62
- options = run_action_group(format('setup_%s', name), **options)
75
+ define_method(name) do |*_args, **options| # rubocop:disable Metrics/MethodLength
76
+ options[:action] ||= name.to_sym
77
+
78
+ options = run_interval(format('setup_%s', name), **options)
63
79
  authorize(name, **options) if respond_to?(:authorize)
64
80
 
65
- options = run_action_group(format('before_%s', name), **options)
81
+ options = run_interval(format('before_%s', name), **options)
66
82
  authorize(name, **options) if respond_to?(:authorize)
67
83
 
68
84
  options = if run_action_primary(method, block, **options)
69
- run_action_group(format('after_%s_success', name), **options)
85
+ run_interval(format('after_%s_success', name), **options)
70
86
  else
71
- run_action_group(format('after_%s_failure', name), **options)
87
+ run_interval(format('after_%s_failure', name), **options)
72
88
  end
73
- run_action_group(format('after_%s', name), **options)
89
+ run_interval(format('after_%s', name), **options)
74
90
  end
75
91
  end
76
92
 
77
- def define_workflow_hooks(name)
78
- hook_builder('setup_%s', name)
79
- hook_builder('before_%s', name)
80
- hook_builder('after_%s_success', name)
81
- hook_builder('after_%s_failure', name)
82
- hook_builder('after_%s', name)
83
- end
84
-
85
- def hook_builder(name_format, name)
86
- assign_singleton_methods format(name_format, name),
87
- format("#{name_format}_hooks", name)
88
- end
89
-
90
- def assign_singleton_methods(method_name, singleton_var)
93
+ def define_singleton_methods(method_name)
94
+ singleton_var = "snfoil_#{method_name}_hooks"
91
95
  instance_variable_set("@#{singleton_var}", [])
92
96
  define_singleton_method(singleton_var) { instance_variable_get("@#{singleton_var}") }
93
97
  define_singleton_method(method_name) do |method = nil, **options, &block|
@@ -99,12 +103,18 @@ module SnFoil
99
103
  unless: options[:unless] }
100
104
  end
101
105
  end
106
+
107
+ def define_instance_methods(method_name)
108
+ define_method(method_name) do |**options|
109
+ options
110
+ end
111
+ end
102
112
  end
103
113
 
104
114
  def run_action_primary(method, block, **options)
105
115
  return send(method, **options) if method
106
116
 
107
- instance_exec options, &block
117
+ instance_exec(**options, &block)
108
118
  end
109
119
  end
110
120
  end
@@ -5,13 +5,13 @@ require_relative 'lib/snfoil/context/version'
5
5
  Gem::Specification.new do |spec|
6
6
  spec.name = 'snfoil-context'
7
7
  spec.version = SnFoil::Context::VERSION
8
- spec.authors = ['Matthew Howes']
9
- spec.email = ['howeszy@gmail.com']
8
+ spec.authors = ['Matthew Howes', 'Cliff Campbell']
9
+ spec.email = ['howeszy@gmail.com', 'cliffcampbell@hey.com']
10
10
 
11
11
  spec.summary = 'Setup simple pipelined workflows'
12
12
  spec.description = 'An easy way to make extensible workflows and actions'
13
13
  spec.homepage = 'https://github.com/limited-effort/snfoil-context'
14
- spec.license = 'MIT'
14
+ spec.license = 'Apache-2.0'
15
15
  spec.required_ruby_version = '>= 2.5.0'
16
16
 
17
17
  spec.metadata['homepage_uri'] = spec.homepage
@@ -30,6 +30,8 @@ Gem::Specification.new do |spec|
30
30
 
31
31
  spec.add_dependency 'activesupport', '>= 5.2.6'
32
32
 
33
+ spec.add_development_dependency 'bundle-audit', '~> 0.1.0'
34
+ spec.add_development_dependency 'fasterer', '~> 0.9.0'
33
35
  spec.add_development_dependency 'pry-byebug', '~> 3.9'
34
36
  spec.add_development_dependency 'rake', '~> 13.0'
35
37
  spec.add_development_dependency 'rspec', '~> 3.10'
metadata CHANGED
@@ -1,14 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: snfoil-context
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matthew Howes
8
+ - Cliff Campbell
8
9
  autorequire:
9
10
  bindir: exe
10
11
  cert_chain: []
11
- date: 2021-10-14 00:00:00.000000000 Z
12
+ date: 2021-10-28 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
15
  name: activesupport
@@ -24,6 +25,34 @@ dependencies:
24
25
  - - ">="
25
26
  - !ruby/object:Gem::Version
26
27
  version: 5.2.6
28
+ - !ruby/object:Gem::Dependency
29
+ name: bundle-audit
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - "~>"
33
+ - !ruby/object:Gem::Version
34
+ version: 0.1.0
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - "~>"
40
+ - !ruby/object:Gem::Version
41
+ version: 0.1.0
42
+ - !ruby/object:Gem::Dependency
43
+ name: fasterer
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - "~>"
47
+ - !ruby/object:Gem::Version
48
+ version: 0.9.0
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - "~>"
54
+ - !ruby/object:Gem::Version
55
+ version: 0.9.0
27
56
  - !ruby/object:Gem::Dependency
28
57
  name: pry-byebug
29
58
  requirement: !ruby/object:Gem::Requirement
@@ -111,10 +140,12 @@ dependencies:
111
140
  description: An easy way to make extensible workflows and actions
112
141
  email:
113
142
  - howeszy@gmail.com
143
+ - cliffcampbell@hey.com
114
144
  executables: []
115
145
  extensions: []
116
146
  extra_rdoc_files: []
117
147
  files:
148
+ - ".fasterer.yml"
118
149
  - ".github/workflows/main.yml"
119
150
  - ".gitignore"
120
151
  - ".rspec"
@@ -135,7 +166,7 @@ files:
135
166
  - snfoil-context.gemspec
136
167
  homepage: https://github.com/limited-effort/snfoil-context
137
168
  licenses:
138
- - MIT
169
+ - Apache-2.0
139
170
  metadata:
140
171
  homepage_uri: https://github.com/limited-effort/snfoil-context
141
172
  source_code_uri: https://github.com/limited-effort/snfoil-context