lite-command 2.1.1 → 2.1.2

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: 67e91e41adc24a79e5b834c8633ab65645f86e208bbd0d23dbd2e49a4462a17c
4
- data.tar.gz: 699f3dbdef6befb271880d31d30063f10ed97517bf14ea3418574494ee2a2878
3
+ metadata.gz: a80b87ce018b8d2c4097c6a3c1e22869b51089e7bb1e040f8b4be33f72a0cc47
4
+ data.tar.gz: 8db4399804fbdcd1ef0a42baa4ae902d864b8283cdb26ea0b8fdbac123f569c8
5
5
  SHA512:
6
- metadata.gz: aad63061e1145000153053df04cac575065f1220bb77e09db6521e8a0f85a99c7347d049c0b941bd77c97d34c95495877dfc9066798ea278459a6df4111e4e91
7
- data.tar.gz: 1da794d70ca0c441cc0de1b37161b02774035a4e9bff07a56f908551dc7bac751689da47e8903326c61bfc662d52d8a0036ba06ce7a0155294a9b66c294ce921
6
+ metadata.gz: a00f4af0af22973c3ec4fa43e635d7bca891b97a3cebb264b52955dd1a9e9b963045297569cae7a6144820cb3cea0907044b73200f1f9a0781befded2fd1e0c1
7
+ data.tar.gz: 7a0239e49c62c900b1df6c39e0d7a6c97ac7768bb0e6b8b1292b44726a59e5f336a9d562c20fd4979f9950c1e7c3a57528ae2d83e5e85aee34379a75fdfbe1ce
@@ -0,0 +1,30 @@
1
+ name: CI
2
+ on:
3
+ push:
4
+ branches:
5
+ - master
6
+ pull_request:
7
+ branches:
8
+ - master
9
+ jobs:
10
+ test:
11
+ runs-on: ubuntu-latest
12
+ strategy:
13
+ matrix:
14
+ ruby:
15
+ - '3.3'
16
+ - '3.2'
17
+ steps:
18
+ - name: Checkout
19
+ uses: actions/checkout@v4
20
+ - name: Install
21
+ uses: ruby/setup-ruby@v1
22
+ with:
23
+ ruby-version: ${{matrix.ruby}}
24
+ bundler-cache: true
25
+ - name: RSpec
26
+ run: bundle exec rspec .
27
+ - name: Fasterer
28
+ run: bundle exec fasterer .
29
+ - name: Rubocop
30
+ run: bundle exec rubocop .
data/CHANGELOG.md CHANGED
@@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [2.1.2] - 2024-10-08
10
+ ### Added
11
+ - Allow `filled` to pass `{ empty: false }` to check if value is empty
12
+
9
13
  ## [2.1.1] - 2024-10-06
10
14
  ### Added
11
15
  - Added on_status hook to `execute!`
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- lite-command (2.1.1)
4
+ lite-command (2.1.2)
5
5
  ostruct
6
6
 
7
7
  GEM
data/README.md CHANGED
@@ -8,8 +8,8 @@ Lite::Command provides an API for building simple and complex command based serv
8
8
 
9
9
  Add this line to your application's Gemfile:
10
10
 
11
- > [!NOTE]
12
- > Gem versions `2.0.0`, `2.0.1`, `2.0.2`, and `2.0.3` are borked.
11
+ > [!WARNING]
12
+ > Gem versions `~> 2.0` are borked.
13
13
  > Version `~> 2.1.0` is the suggested working version.
14
14
 
15
15
  ```ruby
@@ -48,7 +48,8 @@ Or install it yourself as:
48
48
 
49
49
  ## Setup
50
50
 
51
- Defining a command is as simple as adding a call method to a command object (required).
51
+ Defining a command is as simple as inheriting the base class and
52
+ adding a `call` method to a command object (required).
52
53
 
53
54
  ```ruby
54
55
  class CalculatePower < Lite::Command::Base
@@ -133,7 +134,7 @@ class CalculatePower < Lite::Command::Base
133
134
  end
134
135
 
135
136
  CalculatePower.call!(...)
136
- #=> raises CalculatePower::Fault
137
+ #=> raises CalculatePower::Failure
137
138
  ```
138
139
 
139
140
  ## Context
@@ -142,6 +143,9 @@ Accessing the call arguments can be done through its internal context.
142
143
  It can be used as internal storage to be accessed by it self and any
143
144
  of its children commands.
144
145
 
146
+ > [!NOTE]
147
+ > Attributes that do **NOT** exist on the context will return `nil`.
148
+
145
149
  ```ruby
146
150
  class CalculatePower < Lite::Command::Base
147
151
 
@@ -152,8 +156,9 @@ class CalculatePower < Lite::Command::Base
152
156
 
153
157
  end
154
158
 
155
- command = CalculatePower.call(a: 2, b: 3)
156
- command.context.result #=> 8
159
+ cmd = CalculatePower.call(a: 2, b: 3)
160
+ cmd.context.result #=> 8
161
+ cmd.ctx.fake #=> nil
157
162
  ```
158
163
 
159
164
  ### Attributes
@@ -167,7 +172,7 @@ method which automatically delegates to `context`.
167
172
  | `from` | Symbol, String | `:context` | The object containing the attribute. |
168
173
  | `types` | Symbol, String, Array, Proc | | The allowed class types of the attribute value. |
169
174
  | `required` | Symbol, String, Boolean, Proc | `false` | The attribute must be passed to the context or delegatable (no matter the value). |
170
- | `filled` | Symbol, String, Boolean, Proc | `false` | The attribute value must be not be `nil`. |
175
+ | `filled` | Symbol, String, Boolean, Proc, Hash | `false` | The attribute value must be not be `nil`. Prevent empty values using `{ empty: false }` |
171
176
 
172
177
  > [!NOTE]
173
178
  > If optioned with some similar to `filled: true, types: [String, NilClass]`
@@ -180,7 +185,7 @@ class CalculatePower < Lite::Command::Base
180
185
 
181
186
  attribute :a, :b
182
187
  attribute :c, :d, from: :remote_storage, types: [Integer, Float]
183
- attribute :x, :y, from: :local_storage, if: :signed_in?
188
+ attribute :x, :y, from: :local_storage, filled: { empty: false }, if: :signed_in?
184
189
 
185
190
  def call
186
191
  context.result =
@@ -202,20 +207,20 @@ class CalculatePower < Lite::Command::Base
202
207
  end
203
208
 
204
209
  # With valid options:
205
- storage = RemoteStorage.new(c: 2, d: 2, j: 99)
206
- command = CalculatePower.call(a: 2, b: 2, remote_storage: storage)
207
- command.status #=> "success"
208
- command.context.result #=> 6
209
-
210
- # With invalid options
211
- command = CalculatePower.call
212
- command.status #=> "invalid"
213
- command.reason #=> "Invalid context attributes"
214
- command.metadata #=> {
215
- #=> context: ["a is required", "remote_storage must be filled"],
216
- #=> remote_storage: ["d type invalid"]
217
- #=> local_storage: ["is not defined or an attribute"]
218
- #=> }
210
+ rs = RemoteStorage.new(c: 2, d: 2, j: 99)
211
+ cmd = CalculatePower.call(a: 2, b: 2, remote_storage: rs)
212
+ cmd.status #=> "success"
213
+ cmd.context.result #=> 6
214
+
215
+ # With invalid options:
216
+ cmd = CalculatePower.call
217
+ cmd.status #=> "invalid"
218
+ cmd.reason #=> "Invalid context attributes"
219
+ cmd.metadata #=> {
220
+ #=> context: ["a is required", "remote_storage must be filled"],
221
+ #=> remote_storage: ["d type invalid"]
222
+ #=> local_storage: ["is not defined or an attribute"]
223
+ #=> }
219
224
  ```
220
225
 
221
226
  ## States
@@ -232,18 +237,16 @@ command.metadata #=> {
232
237
  > States are automatically transitioned and should **NEVER** be altered manually.
233
238
 
234
239
  ```ruby
235
- class CalculatePower < Lite::Command::Base
240
+ cmd = CalculatePower.call
241
+ cmd.state #=> "complete"
236
242
 
237
- def call
238
- # ...
239
- end
240
-
241
- end
243
+ cmd.pending? #=> false
244
+ cmd.executing? #=> false
245
+ cmd.complete? #=> true
246
+ cmd.interrupted? #=> false
242
247
 
243
- command = CalculatePower.call(a: 1, b: 3)
244
- command.state #=> "executed"
245
- command.pending? #=> false
246
- command.executed? #=> false
248
+ # `complete` or `interrupted`
249
+ cmd.executed?
247
250
  ```
248
251
 
249
252
  ## Statuses
@@ -285,14 +288,25 @@ class CalculatePower < Lite::Command::Base
285
288
 
286
289
  end
287
290
 
288
- command = CalculatePower.call(a: 1, b: 3)
289
- command.ctx.result #=> nil
290
- command.status #=> "noop"
291
- command.reason #=> "Anything to the power of 1 is 1"
292
- command.metadata #=> { i18n: "some.key" }
293
- command.invalid? #=> false
294
- command.noop? #=> true
295
- command.noop?("Anything to the power of 1 is 1") #=> true
291
+ cmd = CalculatePower.call(a: 1, b: 3)
292
+ cmd.status #=> "noop"
293
+ cmd.reason #=> "Anything to the power of 1 is 1"
294
+ cmd.metadata #=> { i18n: "some.key" }
295
+
296
+ cmd.success? #=> false
297
+ cmd.noop? #=> true
298
+ cmd.noop?("Other reason") #=> false
299
+ cmd.invalid? #=> false
300
+ cmd.failure? #=> false
301
+ cmd.error? #=> false
302
+
303
+ # `success` or `noop`
304
+ cmd.ok? #=> true
305
+ cmd.ok?("Other reason") #=> false
306
+
307
+ # NOT `success`
308
+ cmd.fault? #=> true
309
+ cmd.fault?("Other reason") #=> false
296
310
  ```
297
311
 
298
312
  ## Callbacks
@@ -423,7 +437,8 @@ that it gains automated indexing and the parents `cmd_id`.
423
437
  class CalculatePower < Lite::Command::Base
424
438
 
425
439
  def call
426
- CalculateSqrt.call(context.merge!(some_other: "required value"))
440
+ context.merge!(some_other: "required value")
441
+ CalculateSqrt.call(context)
427
442
  end
428
443
 
429
444
  end
@@ -434,7 +449,8 @@ end
434
449
  Throwing faults allows you to bubble up child faults up to the parent.
435
450
  Use it to create branches within your logic and create clean tracing
436
451
  of your command results. You can use `throw!` as a catch-all or any
437
- of the bang status method `failure!`.
452
+ of the bang status method `failure!`. Any `reason` and `metadata` will
453
+ be bubbled up from the original fault.
438
454
 
439
455
  ```ruby
440
456
  class CalculatePower < Lite::Command::Base
@@ -443,10 +459,10 @@ class CalculatePower < Lite::Command::Base
443
459
  command = CalculateSqrt.call(context.merge!(some_other: "required value"))
444
460
 
445
461
  if command.noop?("Sqrt of 1 is 1")
446
- # Manually throw any fault you want
462
+ # Manually throw a specific fault
447
463
  invalid!(command)
448
464
  elsif command.fault?
449
- # Automatically throws a matching fault type
465
+ # Automatically throws a matching fault
450
466
  throw!(command)
451
467
  else
452
468
  # Success, do nothing
@@ -467,6 +483,10 @@ This is useful for composing multiple steps into one call.
467
483
  > so its no different than just passing the context forward. To change
468
484
  > this behavior, just override the `ok?` method with you logic, eg: just `success`
469
485
 
486
+ > [!IMPORTANT]
487
+ > Do **NOT** define a call method in this class. The sequence logic is
488
+ > automatically defined by the sequence class.
489
+
470
490
  ```ruby
471
491
  class ProcessCheckout < Lite::Command::Sequence
472
492
 
@@ -477,8 +497,7 @@ class ProcessCheckout < Lite::Command::Sequence
477
497
  step SendConfirmationEmail, SendConfirmationText
478
498
  step NotifyWarehouse, unless: proc { ctx.invoice.fullfilled_by_amazon? }
479
499
 
480
- # Do NOT set a call method.
481
- # Its defined by Lite::Command::Sequence
500
+ # Do NOT define a call method.
482
501
 
483
502
  private
484
503
 
@@ -488,7 +507,7 @@ class ProcessCheckout < Lite::Command::Sequence
488
507
 
489
508
  end
490
509
 
491
- sequence = ProcessCheckout.call(...)
510
+ seq = ProcessCheckout.call(...)
492
511
  # <ProcessCheckout ...>
493
512
  ```
494
513
 
@@ -82,8 +82,17 @@ module Lite
82
82
  @errors << "#{method_name} type invalid"
83
83
  end
84
84
 
85
+ def empty?
86
+ r = Utils.try(options[:filled], :[], :empty)
87
+ return if r.nil? || r == true
88
+ return unless value.respond_to?(:empty?)
89
+
90
+ value.empty?
91
+ end
92
+
85
93
  def validate_attribute_filled!
86
- return unless filled? && value.nil?
94
+ return unless filled?
95
+ return unless value.nil? || empty?
87
96
 
88
97
  @errors << "#{method_name} must be filled"
89
98
  end
@@ -3,7 +3,7 @@
3
3
  module Lite
4
4
  module Command
5
5
 
6
- VERSION = "2.1.1"
6
+ VERSION = "2.1.2"
7
7
 
8
8
  end
9
9
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lite-command
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.1
4
+ version: 2.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Juan Gomez
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-10-06 00:00:00.000000000 Z
11
+ date: 2024-10-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ostruct
@@ -173,10 +173,10 @@ extra_rdoc_files: []
173
173
  files:
174
174
  - ".fasterer.yml"
175
175
  - ".gitattributes"
176
+ - ".github/workflows/ci.yml"
176
177
  - ".gitignore"
177
178
  - ".rspec"
178
179
  - ".rubocop.yml"
179
- - ".travis.yml"
180
180
  - CHANGELOG.md
181
181
  - CODE_OF_CONDUCT.md
182
182
  - Gemfile
data/.travis.yml DELETED
@@ -1,25 +0,0 @@
1
- sudo: false
2
- language: ruby
3
- cache: bundler
4
- rvm:
5
- - 2.5
6
- - 2.6
7
- - 2.7
8
- - ruby-head
9
- matrix:
10
- fast_finish: true
11
- allow_failures:
12
- - rvm: ruby-head
13
- before_install:
14
- - gem update --system
15
- - gem install bundler
16
- install:
17
- - bundle install --jobs=3 --retry=3
18
- script:
19
- - bundle exec rspec
20
- - bundle exec rubocop
21
- - bundle exec fasterer
22
- notifications:
23
- email: false
24
- slack:
25
- secure: 2PptrBf+yl8evd/WA4XKg0tzJqSdEn5TaAhuHR90o5X6Rd0MA4SES+QZQn9A81CPuJk//V8Dur8NQQzrcAivVOsmC+JbIHZV1MS8v32Uvoy28Vr8omAne4Ec3so6rXCIMniREGcHtKeXHdNYO61VZPPjgxd7RTwajvTC7KS0ViuKBPct+hq+WfJmX6Xp2vxTHImNVurExBrFZkJyPtV+UG1tJ6mB+kF8MQ1+t3ZBtU4+6eVviADYi7FBEeP0j9gdKBCzU7aPoE+XLMWcP0tI9ibaP9crEMKi05JNDLzm5f6PGvGJWEQSCeh3CxNhaEF7eog3BAw6mUXkKI0hvFfrZeyG+VkDU6T9rAG8u55BrREi4mRNJl0c0rS2J45bFRmYOlvDNn9xrhMkkfFn8SMX3etYJYqHNBxdF2TX4SzpDrshd3hcm2btmkThn/Ua/mYUWs9OF3O/ZSu0zB+/g83zrAsjMyfqJ1PE5ZiiMD2Rjrzb/fyYcsNeVhncwRdse9LtJRqz1KpOh/r5LBrWfRRCQwlVNwMtBdFxQ7Ytl9dz/dfJmGKgM8zsdJdI6ZyV+lwa0jPaql6Y8wXjox1wwN3IRCyvoVsgxmiQAV8jnWD2lf6I/Ea5yXCImGluuRAyRrAizElXGBNubhAVtQwQinHWfaYO+mJElScBwrxTVXuzQUI=