lite-command 2.0.0 → 2.0.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 340d00e30b3a4ca140aaff5ee354c8c48d43e03a35533a69ea349afb8c429435
4
- data.tar.gz: f05f29f0fcc6d55c2afe9cb4debb309491374db238f9bfdcbe3833169c5caeeb
3
+ metadata.gz: 1a841431a363de96b59d32abaa1bc733c04046a5d2f33b1c544e85b8b89cdcd9
4
+ data.tar.gz: 11dd1cd8c8e19cc8d58a631f94f647eb4d7a6b2effe2591d04eaea4c693ecdee
5
5
  SHA512:
6
- metadata.gz: e504efb0c085b59b57cbc05fb344c9568ee0ad18a275af25efef9cd3db6e5f6dde9b25dfbf971e1b34cab864c486c6efd6dabd015cb23f5ee1199abc0d85956f
7
- data.tar.gz: 5ee4f05437705a5ed44a529cf776f32f0b5b049f020f7de8615c0aa1a1e47601db6b4d54cc381cd2280238e4e5d00f2b626c07688aa65795955cdc8092279f15
6
+ metadata.gz: ae2440d1e33ddf601c42996a513f66771fb06af24a6f60534329b3337335bb714e3be2e9fd5b43d5f71e26ff8d2bc5bbe7bc9a07d275b259491858f6f8864e9b
7
+ data.tar.gz: 873edb0d145a80033180e0a33072dd80da38512511d718af17e4e91ddc65d90118bd63d8a341d22278a1d026751b0cf867df708dafde21be54fc54ef0c821f47
data/CHANGELOG.md CHANGED
@@ -6,7 +6,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
- ## [2.0.0] - 2024-09-22
9
+ ## [2.0.2] - 2024-09-29
10
+ ### Added
11
+ - faultable module
12
+ ### Changed
13
+ - Simplified status variable check
14
+ - Simplified context merge
15
+ - Fixed invalid looking at wrong variable
16
+ - Renamed `fault` and `thrower` to `caused_by` and `thrown_by` respectively
17
+ - Removed unused `additional_result_data` method
18
+ ### Removed
19
+ - Removed context init
20
+
21
+ ## [2.0.1] - 2024-09-27
22
+ ### Removed
23
+ - Activemodel dependency
24
+
25
+ ## [2.0.0] - 2024-09-27
10
26
  ### Changed
11
27
  - Rewrite app to use interactor pattern
12
28
 
data/Gemfile.lock CHANGED
@@ -1,8 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- lite-command (2.0.0)
5
- activemodel
4
+ lite-command (2.0.2)
6
5
  ostruct
7
6
 
8
7
  GEM
@@ -25,8 +24,6 @@ GEM
25
24
  erubi (~> 1.11)
26
25
  rails-dom-testing (~> 2.2)
27
26
  rails-html-sanitizer (~> 1.6)
28
- activemodel (7.2.1)
29
- activesupport (= 7.2.1)
30
27
  activesupport (7.2.1)
31
28
  base64
32
29
  bigdecimal
@@ -9,6 +9,7 @@ module Lite
9
9
 
10
10
  base.include Lite::Command::Internals::Callable
11
11
  base.include Lite::Command::Internals::Executable
12
+ base.include Lite::Command::Internals::Faultable
12
13
  base.include Lite::Command::Internals::Resultable
13
14
 
14
15
  base.class_eval <<-RUBY, __FILE__, __LINE__ + 1
@@ -25,6 +26,7 @@ module Lite
25
26
  end
26
27
 
27
28
  attr_reader :context
29
+ alias ctx context
28
30
 
29
31
  def initialize(context = {})
30
32
  @context = Lite::Command::Context.build(context)
@@ -32,10 +34,6 @@ module Lite
32
34
 
33
35
  private
34
36
 
35
- def additional_result_data
36
- {} # Define in your class to add additional info to result hash
37
- end
38
-
39
37
  def on_before_execution
40
38
  # Define in your class to run code before execution
41
39
  end
@@ -6,25 +6,20 @@ module Lite
6
6
  module Command
7
7
  class Context < OpenStruct
8
8
 
9
- def self.init(attributes = {})
9
+ def self.build(attributes = {})
10
+ return attributes if attributes.is_a?(self) && !attributes.frozen?
11
+
10
12
  # To save memory and speed up the access to an attribute, the accessor methods
11
13
  # of an attribute are lazy loaded at certain points. This means that the methods
12
14
  # are defined only when a set of defined actions are triggered. This allows context
13
15
  # to only define the minimum amount of required methods to make your data structure work
14
- os = new(attributes)
16
+ os = new(attributes.to_h)
15
17
  os.methods(false)
16
18
  os
17
19
  end
18
20
 
19
- def self.build(attributes = {})
20
- return attributes if attributes.is_a?(self) && !attributes.frozen?
21
-
22
- init(attributes.to_h)
23
- end
24
-
25
21
  def merge!(attributes = {})
26
- attrs = attributes.is_a?(self.class) ? attributes.to_h : attributes
27
- attrs.each { |k, v| self[k] = v }
22
+ attributes.to_h.each { |k, v| self[k] = v }
28
23
  end
29
24
 
30
25
  end
@@ -3,18 +3,15 @@
3
3
  module Lite
4
4
  module Command
5
5
 
6
- # Fault represent a stoppage of a call execution. This error should
7
- # not be raised directly since it wont provide any context. Use
8
- # `Noop`, `Invalid`, `Failure`, and `Error` to signify severity.
9
6
  class Fault < StandardError
10
7
 
11
- attr_reader :faulter, :thrower, :reason
8
+ attr_reader :caused_by, :thrown_by, :reason
12
9
 
13
- def initialize(faulter, thrower, reason)
10
+ def initialize(caused_by, thrown_by, reason)
14
11
  super(reason)
15
12
 
16
- @faulter = faulter
17
- @thrower = thrower
13
+ @caused_by = caused_by
14
+ @thrown_by = thrown_by
18
15
  @reason = reason
19
16
  end
20
17
 
@@ -28,26 +25,9 @@ module Lite
28
25
 
29
26
  end
30
27
 
31
- # Noop represents skipping completion of call execution early
32
- # an unsatisfied condition or logic check where there is no
33
- # point on proceeding.
34
- # eg: account is sample: skip since its a non-alterable record
35
28
  class Noop < Fault; end
36
-
37
- # Invalid represents a stoppage of call execution due to
38
- # missing, bad, or corrupt data.
39
- # eg: user not found: stop since rest of the call cant be executed
40
29
  class Invalid < Fault; end
41
-
42
- # Failure represents a stoppage of call execution due to
43
- # an unsatisfied condition or logic check where it blocks
44
- # proceeding any further.
45
- # eg: record not found: stop since there is nothing todo
46
30
  class Failure < Fault; end
47
-
48
- # Error represents a caught exception for a call execution
49
- # that could not complete.
50
- # eg: ApiServerError: stop since there was a 3rd party issue
51
31
  class Error < Fault; end
52
32
 
53
33
  end
@@ -3,28 +3,20 @@
3
3
  module Lite
4
4
  module Command
5
5
 
6
- # Status represents the state of the callable code. If no fault
7
- # is thrown then a status of SUCCESS is returned even if `call`
8
- # has not been executed.
9
- FAULTS = [
6
+ STATUSES = [
7
+ SUCCESS = "success",
10
8
  NOOP = "noop",
11
9
  INVALID = "invalid",
12
10
  FAILURE = "failure",
13
11
  ERROR = "error"
14
12
  ].freeze
15
- STATUSES = [
16
- *FAULTS,
17
- SUCCESS = "success"
18
- ].freeze
13
+ FAULTS = (STATUSES - [SUCCESS]).freeze
19
14
 
20
15
  module Internals
21
16
  module Callable
22
17
 
23
18
  def self.included(base)
24
19
  base.extend ClassMethods
25
- base.class_eval do
26
- attr_reader :faulter, :thrower, :reason
27
- end
28
20
  end
29
21
 
30
22
  module ClassMethods
@@ -43,109 +35,44 @@ module Lite
43
35
  raise NotImplementedError, "call method not defined in #{self.class}"
44
36
  end
45
37
 
46
- def success?
47
- !fault?
48
- end
49
-
50
- def fault?(message = nil)
51
- FAULTS.any? { |f| send(:"#{f}?", message) }
52
- end
53
-
54
38
  def status
55
- STATUSES.find { |s| send(:"#{s}?") }
56
- end
57
-
58
- def faulter?
59
- faulter == self
39
+ @status || SUCCESS
60
40
  end
61
41
 
62
- def thrower?
63
- thrower == self
42
+ def success?
43
+ status == SUCCESS
64
44
  end
65
45
 
66
- def thrown_fault?
67
- fault? && !faulter?
46
+ def fault?(str = nil)
47
+ !success? && reason?(str)
68
48
  end
69
49
 
70
50
  FAULTS.each do |f|
71
- # eg: error?(message = nil)
72
- define_method(:"#{f}?") do |message = nil|
73
- fault_result = instance_variable_get(:"@#{f}") || false
74
- return fault_result if message.nil?
75
-
76
- reason == message
51
+ # eg: noop? or failure?("idk")
52
+ define_method(:"#{f}?") do |str = nil|
53
+ status == f && reason?(str)
77
54
  end
78
55
  end
79
56
 
80
57
  private
81
58
 
82
- def derive_faulter_from(object)
83
- (object.faulter if object.respond_to?(:faulter)) || self
84
- end
85
-
86
- def derive_thrower_from(object)
87
- if object.respond_to?(:executed?) && object.executed?
88
- object
89
- else
90
- (object.thrower if object.respond_to?(:thrower)) || faulter
91
- end
92
- end
93
-
94
- def derive_reason_from(object)
95
- if object.respond_to?(:reason)
96
- object.reason
97
- elsif object.respond_to?(:message)
98
- "[#{object.class.name}] #{object.message}".chomp(".")
99
- else
100
- object
101
- end
102
- end
103
-
104
- def fault(object)
105
- @faulter ||= derive_faulter_from(object)
106
- @thrower ||= derive_thrower_from(object)
107
- @reason ||= derive_reason_from(object)
108
- end
109
-
110
- # eg: Lite::Command::Noop.new(...)
111
- def raise_fault(klass, object)
112
- exception = klass.new(faulter, self, reason)
113
- exception.set_backtrace(object.backtrace) if object.respond_to?(:backtrace)
114
- raise(exception)
115
- end
116
-
117
- # eg: Users::ResetPassword::Noop.new(...)
118
- def raise_dynamic_fault(exception)
119
- fault_klass = self.class.const_get(exception.fault_klass)
120
- raise_fault(fault_klass, exception)
121
- end
122
-
123
- def raise_dynamic_faults?
124
- false
125
- end
126
-
127
- def throw!(command)
128
- return if command.success?
129
-
130
- send(:"#{command.status}!", command)
131
- end
132
-
133
59
  FAULTS.each do |f|
134
- # eg: error(object)
135
- define_method(:"#{f}") do |object|
136
- fault(object)
137
- instance_variable_set(:"@#{f}", true)
60
+ # eg: error(fault_or_string)
61
+ define_method(:"#{f}") do |fault_or_string|
62
+ derive_fault_from(fault_or_string)
63
+ @status = f
138
64
  end
139
65
 
140
- # eg: invalid!(object)
141
- define_method(:"#{f}!") do |object|
142
- send(:"#{f}", object)
143
- raise_fault(Lite::Command.const_get(f.capitalize), object)
66
+ # eg: invalid!(fault_or_string)
67
+ define_method(:"#{f}!") do |fault_or_string|
68
+ send(:"#{f}", fault_or_string)
69
+ raise_fault(Lite::Command.const_get(f.capitalize), fault_or_string)
144
70
  end
145
71
 
146
72
  # eg: on_noop(exception)
147
73
  define_method(:"on_#{f}") do |_exception|
148
- # Define in your class to run code when a StandardError happens
74
+ # Define in your class to run code when a
75
+ # Lite::Command::Fault or StandardError happens
149
76
  end
150
77
  end
151
78
 
@@ -3,9 +3,6 @@
3
3
  module Lite
4
4
  module Command
5
5
 
6
- # State represents the state of the executable code. Once `execute`
7
- # is ran, it will always complete or dnf if a fault is thrown by a
8
- # child command.
9
6
  STATES = [
10
7
  PENDING = "pending",
11
8
  EXECUTING = "executing",
@@ -45,7 +42,7 @@ module Lite
45
42
  end
46
43
 
47
44
  STATES.each do |s|
48
- # eg: running?
45
+ # eg: executing?
49
46
  define_method(:"#{s}?") { state == s }
50
47
 
51
48
  # eg: dnf!
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Lite
4
+ module Command
5
+ module Internals
6
+ module Faultable
7
+
8
+ def self.included(base)
9
+ base.class_eval do
10
+ attr_reader :caused_by, :thrown_by, :reason
11
+ end
12
+ end
13
+
14
+ def reason?(str)
15
+ return true if str.nil?
16
+
17
+ reason == str
18
+ end
19
+
20
+ def caused_fault?
21
+ caused_by == self
22
+ end
23
+
24
+ def threw_fault?
25
+ thrown_by == self
26
+ end
27
+
28
+ def thrown?
29
+ fault? && !caused_fault?
30
+ end
31
+
32
+ private
33
+
34
+ def throw!(command)
35
+ return if command.success?
36
+
37
+ send(:"#{command.status}!", command)
38
+ end
39
+
40
+ def derive_caused_by_from(fault_or_string)
41
+ (fault_or_string.caused_by if fault_or_string.respond_to?(:caused_by)) || self
42
+ end
43
+
44
+ def derive_thrown_by_from(fault_or_string)
45
+ if fault_or_string.respond_to?(:executed?) && fault_or_string.executed?
46
+ fault_or_string
47
+ else
48
+ (fault_or_string.thrown_by if fault_or_string.respond_to?(:thrown_by)) || caused_by
49
+ end
50
+ end
51
+
52
+ def derive_reason_from(fault_or_string)
53
+ if fault_or_string.respond_to?(:reason)
54
+ fault_or_string.reason
55
+ elsif fault_or_string.respond_to?(:message)
56
+ "[#{fault_or_string.class.name}] #{fault_or_string.message}".chomp(".")
57
+ else
58
+ fault_or_string
59
+ end
60
+ end
61
+
62
+ def derive_fault_from(fault_or_string)
63
+ @caused_by ||= derive_caused_by_from(fault_or_string)
64
+ @thrown_by ||= derive_thrown_by_from(fault_or_string)
65
+ @reason ||= derive_reason_from(fault_or_string)
66
+ end
67
+
68
+ # eg: Lite::Command::Noop.new(...)
69
+ def raise_fault(klass, thrower)
70
+ exception = klass.new(caused_by, self, reason)
71
+ exception.set_backtrace(thrower.backtrace) if thrower.respond_to?(:backtrace)
72
+ raise(exception)
73
+ end
74
+
75
+ # eg: Users::ResetPassword::Noop.new(...)
76
+ def raise_dynamic_fault(exception)
77
+ fault_klass = self.class.const_get(exception.fault_klass)
78
+ raise_fault(fault_klass, exception)
79
+ end
80
+
81
+ def raise_dynamic_faults?
82
+ false
83
+ end
84
+
85
+ end
86
+ end
87
+ end
88
+ end
@@ -16,7 +16,7 @@ module Lite
16
16
  end
17
17
 
18
18
  def outcome
19
- return state if pending? || thrown_fault?
19
+ return state if pending? || thrown?
20
20
 
21
21
  status
22
22
  end
@@ -34,8 +34,8 @@ module Lite
34
34
  state:,
35
35
  status:,
36
36
  reason:,
37
- fault: faulter&.index,
38
- throw: thrower&.index,
37
+ caused_by: caused_by&.index,
38
+ thrown_by: thrown_by&.index,
39
39
  runtime:
40
40
  }.compact
41
41
  end
@@ -3,7 +3,7 @@
3
3
  module Lite
4
4
  module Command
5
5
 
6
- VERSION = "2.0.0"
6
+ VERSION = "2.0.2"
7
7
 
8
8
  end
9
9
  end
data/lib/lite/command.rb CHANGED
@@ -5,6 +5,7 @@ require "generators/rails/command_generator" if defined?(Rails::Generators)
5
5
  require "lite/command/version"
6
6
  require "lite/command/internals/callable"
7
7
  require "lite/command/internals/executable"
8
+ require "lite/command/internals/faultable"
8
9
  require "lite/command/internals/resultable"
9
10
  require "lite/command/fault"
10
11
  require "lite/command/context"
data/lite-command.gemspec CHANGED
@@ -37,7 +37,6 @@ Gem::Specification.new do |spec|
37
37
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
38
38
  spec.require_paths = %w[lib]
39
39
 
40
- spec.add_dependency "activemodel"
41
40
  spec.add_dependency "ostruct"
42
41
 
43
42
  spec.add_development_dependency "bundler"
metadata CHANGED
@@ -1,29 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lite-command
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
4
+ version: 2.0.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-09-27 00:00:00.000000000 Z
11
+ date: 2024-09-29 00:00:00.000000000 Z
12
12
  dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: activemodel
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - ">="
18
- - !ruby/object:Gem::Version
19
- version: '0'
20
- type: :runtime
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - ">="
25
- - !ruby/object:Gem::Version
26
- version: '0'
27
13
  - !ruby/object:Gem::Dependency
28
14
  name: ostruct
29
15
  requirement: !ruby/object:Gem::Requirement
@@ -210,6 +196,7 @@ files:
210
196
  - lib/lite/command/fault.rb
211
197
  - lib/lite/command/internals/callable.rb
212
198
  - lib/lite/command/internals/executable.rb
199
+ - lib/lite/command/internals/faultable.rb
213
200
  - lib/lite/command/internals/resultable.rb
214
201
  - lib/lite/command/version.rb
215
202
  - lite-command.gemspec
@@ -233,7 +220,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
233
220
  - !ruby/object:Gem::Version
234
221
  version: '0'
235
222
  requirements: []
236
- rubygems_version: 3.5.19
223
+ rubygems_version: 3.5.20
237
224
  signing_key:
238
225
  specification_version: 4
239
226
  summary: Ruby Command based framework (aka service objects)