lite-command 1.4.1 → 2.0.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 +4 -4
- data/.rubocop.yml +23 -2
- data/CHANGELOG.md +10 -0
- data/Gemfile +1 -1
- data/Gemfile.lock +131 -105
- data/README.md +85 -218
- data/Rakefile +2 -2
- data/bin/console +3 -3
- data/lib/generators/rails/command_generator.rb +5 -5
- data/lib/generators/rails/templates/command.rb.tt +1 -1
- data/lib/lite/command/base.rb +49 -0
- data/lib/lite/command/context.rb +32 -0
- data/lib/lite/command/fault.rb +54 -0
- data/lib/lite/command/internals/callable.rb +158 -0
- data/lib/lite/command/internals/executable.rb +83 -0
- data/lib/lite/command/internals/resultable.rb +78 -0
- data/lib/lite/command/version.rb +1 -1
- data/lib/lite/command.rb +9 -13
- data/lite-command.gemspec +28 -29
- metadata +13 -42
- data/lib/lite/command/complex.rb +0 -50
- data/lib/lite/command/exceptions.rb +0 -11
- data/lib/lite/command/extensions/errors.rb +0 -88
- data/lib/lite/command/extensions/memoize.rb +0 -17
- data/lib/lite/command/extensions/propagation.rb +0 -37
- data/lib/lite/command/procedure.rb +0 -51
- data/lib/lite/command/simple.rb +0 -19
- data/lib/lite/command/states.rb +0 -31
@@ -0,0 +1,158 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Lite
|
4
|
+
module Command
|
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 = [
|
10
|
+
NOOP = "noop",
|
11
|
+
INVALID = "invalid",
|
12
|
+
FAILURE = "failure",
|
13
|
+
ERROR = "error"
|
14
|
+
].freeze
|
15
|
+
STATUSES = [
|
16
|
+
*FAULTS,
|
17
|
+
SUCCESS = "success"
|
18
|
+
].freeze
|
19
|
+
|
20
|
+
module Internals
|
21
|
+
module Callable
|
22
|
+
|
23
|
+
def self.included(base)
|
24
|
+
base.extend ClassMethods
|
25
|
+
base.class_eval do
|
26
|
+
attr_reader :faulter, :thrower, :reason
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
module ClassMethods
|
31
|
+
|
32
|
+
def call(context = {})
|
33
|
+
new(context).tap(&:execute)
|
34
|
+
end
|
35
|
+
|
36
|
+
def call!(context = {})
|
37
|
+
new(context).tap(&:execute!)
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
def call
|
43
|
+
raise NotImplementedError, "call method not defined in #{self.class}"
|
44
|
+
end
|
45
|
+
|
46
|
+
def success?
|
47
|
+
!fault?
|
48
|
+
end
|
49
|
+
|
50
|
+
def fault?(message = nil)
|
51
|
+
FAULTS.any? { |f| send(:"#{f}?", message) }
|
52
|
+
end
|
53
|
+
|
54
|
+
def status
|
55
|
+
STATUSES.find { |s| send(:"#{s}?") }
|
56
|
+
end
|
57
|
+
|
58
|
+
def faulter?
|
59
|
+
faulter == self
|
60
|
+
end
|
61
|
+
|
62
|
+
def thrower?
|
63
|
+
thrower == self
|
64
|
+
end
|
65
|
+
|
66
|
+
def thrown_fault?
|
67
|
+
fault? && !faulter?
|
68
|
+
end
|
69
|
+
|
70
|
+
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
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
private
|
81
|
+
|
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
|
+
FAULTS.each do |f|
|
134
|
+
# eg: error(object)
|
135
|
+
define_method(:"#{f}") do |object|
|
136
|
+
fault(object)
|
137
|
+
instance_variable_set(:"@#{f}", true)
|
138
|
+
end
|
139
|
+
|
140
|
+
# eg: invalid!(object)
|
141
|
+
define_method(:"#{f}!") do |object|
|
142
|
+
send(:"#{f}", object)
|
143
|
+
raise_fault(Lite::Command.const_get(f.capitalize), object)
|
144
|
+
end
|
145
|
+
|
146
|
+
# eg: on_noop(exception)
|
147
|
+
define_method(:"on_#{f}") do |_exception|
|
148
|
+
# Define in your class to run code when a StandardError happens
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
alias fail! failure!
|
153
|
+
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
end
|
158
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Lite
|
4
|
+
module Command
|
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
|
+
STATES = [
|
10
|
+
PENDING = "pending",
|
11
|
+
EXECUTING = "executing",
|
12
|
+
COMPLETE = "complete",
|
13
|
+
DNF = "dnf"
|
14
|
+
].freeze
|
15
|
+
|
16
|
+
module Internals
|
17
|
+
module Executable
|
18
|
+
|
19
|
+
def execute
|
20
|
+
around_execution { call }
|
21
|
+
rescue StandardError => e
|
22
|
+
fn = e.respond_to?(:fault_name) ? e.fault_name : ERROR
|
23
|
+
|
24
|
+
send(:"#{fn}", e)
|
25
|
+
after_execution
|
26
|
+
send(:"on_#{fn}", e)
|
27
|
+
end
|
28
|
+
|
29
|
+
def execute!
|
30
|
+
around_execution { call }
|
31
|
+
rescue StandardError => e
|
32
|
+
after_execution
|
33
|
+
|
34
|
+
raise(e) unless raise_dynamic_faults? && e.is_a?(Lite::Command::Fault)
|
35
|
+
|
36
|
+
raise_dynamic_fault(e)
|
37
|
+
end
|
38
|
+
|
39
|
+
def state
|
40
|
+
@state || PENDING
|
41
|
+
end
|
42
|
+
|
43
|
+
def executed?
|
44
|
+
dnf? || complete?
|
45
|
+
end
|
46
|
+
|
47
|
+
STATES.each do |s|
|
48
|
+
# eg: running?
|
49
|
+
define_method(:"#{s}?") { state == s }
|
50
|
+
|
51
|
+
# eg: dnf!
|
52
|
+
define_method(:"#{s}!") { @state = s }
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def before_execution
|
58
|
+
increment_execution_index
|
59
|
+
assign_execution_cid
|
60
|
+
start_monotonic_time
|
61
|
+
executing!
|
62
|
+
on_before_execution
|
63
|
+
end
|
64
|
+
|
65
|
+
def after_execution
|
66
|
+
fault? ? dnf! : complete!
|
67
|
+
on_after_execution
|
68
|
+
stop_monotonic_time
|
69
|
+
append_execution_result
|
70
|
+
freeze_execution_objects
|
71
|
+
end
|
72
|
+
|
73
|
+
def around_execution
|
74
|
+
before_execution
|
75
|
+
yield
|
76
|
+
after_execution
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "securerandom" unless defined?(SecureRandom)
|
4
|
+
|
5
|
+
module Lite
|
6
|
+
module Command
|
7
|
+
module Internals
|
8
|
+
module Resultable
|
9
|
+
|
10
|
+
def index
|
11
|
+
@index ||= context.index ||= 0
|
12
|
+
end
|
13
|
+
|
14
|
+
def cid
|
15
|
+
@cid ||= context.cid
|
16
|
+
end
|
17
|
+
|
18
|
+
def outcome
|
19
|
+
return state if pending? || thrown_fault?
|
20
|
+
|
21
|
+
status
|
22
|
+
end
|
23
|
+
|
24
|
+
def results
|
25
|
+
@results ||= context.results ||= []
|
26
|
+
end
|
27
|
+
|
28
|
+
def to_hash
|
29
|
+
{
|
30
|
+
index:,
|
31
|
+
cid:,
|
32
|
+
command: self.class.name,
|
33
|
+
outcome:,
|
34
|
+
state:,
|
35
|
+
status:,
|
36
|
+
reason:,
|
37
|
+
fault: faulter&.index,
|
38
|
+
throw: thrower&.index,
|
39
|
+
runtime:
|
40
|
+
}.compact
|
41
|
+
end
|
42
|
+
alias to_h to_hash
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def assign_execution_cid
|
47
|
+
context.cid ||= SecureRandom.uuid
|
48
|
+
end
|
49
|
+
|
50
|
+
def increment_execution_index
|
51
|
+
@index = context.index = index.next
|
52
|
+
end
|
53
|
+
|
54
|
+
def start_monotonic_time
|
55
|
+
@start_monotonic_time ||= Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
56
|
+
end
|
57
|
+
|
58
|
+
def stop_monotonic_time
|
59
|
+
@stop_monotonic_time ||= Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
60
|
+
end
|
61
|
+
|
62
|
+
def runtime
|
63
|
+
stop_monotonic_time - start_monotonic_time
|
64
|
+
end
|
65
|
+
|
66
|
+
def append_execution_result
|
67
|
+
results.push(self).sort_by!(&:index)
|
68
|
+
end
|
69
|
+
|
70
|
+
def freeze_execution_objects
|
71
|
+
context.freeze if index == 1
|
72
|
+
freeze
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
data/lib/lite/command/version.rb
CHANGED
data/lib/lite/command.rb
CHANGED
@@ -1,15 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
|
5
|
-
require
|
6
|
-
|
7
|
-
require
|
8
|
-
require
|
9
|
-
require
|
10
|
-
|
11
|
-
require
|
12
|
-
require 'lite/command/states'
|
13
|
-
require 'lite/command/simple'
|
14
|
-
require 'lite/command/complex'
|
15
|
-
require 'lite/command/procedure'
|
3
|
+
require "generators/rails/command_generator" if defined?(Rails::Generators)
|
4
|
+
|
5
|
+
require "lite/command/version"
|
6
|
+
require "lite/command/internals/callable"
|
7
|
+
require "lite/command/internals/executable"
|
8
|
+
require "lite/command/internals/resultable"
|
9
|
+
require "lite/command/fault"
|
10
|
+
require "lite/command/context"
|
11
|
+
require "lite/command/base"
|
data/lite-command.gemspec
CHANGED
@@ -1,55 +1,54 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
lib = File.expand_path(
|
3
|
+
lib = File.expand_path("../lib", __FILE__)
|
4
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
-
require
|
5
|
+
require "lite/command/version"
|
6
6
|
|
7
7
|
Gem::Specification.new do |spec|
|
8
|
-
spec.name =
|
8
|
+
spec.name = "lite-command"
|
9
9
|
spec.version = Lite::Command::VERSION
|
10
|
-
spec.authors = [
|
10
|
+
spec.authors = ["Juan Gomez"]
|
11
11
|
spec.email = %w[j.gomez@drexed.com]
|
12
12
|
|
13
|
-
spec.summary =
|
14
|
-
spec.homepage =
|
15
|
-
spec.license =
|
13
|
+
spec.summary = "Ruby Command based framework (aka service objects)"
|
14
|
+
spec.homepage = "http://drexed.github.io/lite-command"
|
15
|
+
spec.license = "MIT"
|
16
16
|
|
17
17
|
# Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
|
18
18
|
# to allow pushing to a single host or delete this section to allow pushing to any host.
|
19
19
|
if spec.respond_to?(:metadata)
|
20
20
|
spec.metadata.merge(
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
21
|
+
"allowed_push_host" => "https://rubygems.org",
|
22
|
+
"changelog_uri" => "https://github.com/drexed/lite-command/blob/master/CHANGELOG.md",
|
23
|
+
"homepage_uri" => spec.homepage,
|
24
|
+
"source_code_uri" => "https://github.com/drexed/lite-command"
|
25
25
|
)
|
26
26
|
else
|
27
|
-
raise
|
28
|
-
|
27
|
+
raise "RubyGems 2.0 or newer is required to protect against " \
|
28
|
+
"public gem pushes."
|
29
29
|
end
|
30
30
|
|
31
31
|
# Specify which files should be added to the gem when it is released.
|
32
32
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
33
|
-
spec.files = Dir.chdir(File.expand_path(
|
33
|
+
spec.files = Dir.chdir(File.expand_path("..", __FILE__)) do
|
34
34
|
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
35
35
|
end
|
36
|
-
spec.bindir =
|
36
|
+
spec.bindir = "exe"
|
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
|
41
|
-
spec.add_dependency
|
40
|
+
spec.add_dependency "activemodel"
|
41
|
+
spec.add_dependency "ostruct"
|
42
42
|
|
43
|
-
spec.add_development_dependency
|
44
|
-
spec.add_development_dependency
|
45
|
-
spec.add_development_dependency
|
46
|
-
spec.add_development_dependency
|
47
|
-
spec.add_development_dependency
|
48
|
-
spec.add_development_dependency
|
49
|
-
spec.add_development_dependency
|
50
|
-
spec.add_development_dependency
|
51
|
-
spec.add_development_dependency
|
52
|
-
spec.add_development_dependency
|
53
|
-
spec.
|
54
|
-
spec.add_development_dependency 'sqlite3'
|
43
|
+
spec.add_development_dependency "bundler"
|
44
|
+
spec.add_development_dependency "fasterer"
|
45
|
+
spec.add_development_dependency "generator_spec"
|
46
|
+
spec.add_development_dependency "rake"
|
47
|
+
spec.add_development_dependency "rspec"
|
48
|
+
spec.add_development_dependency "rubocop"
|
49
|
+
spec.add_development_dependency "rubocop-performance"
|
50
|
+
spec.add_development_dependency "rubocop-rake"
|
51
|
+
spec.add_development_dependency "rubocop-rspec"
|
52
|
+
spec.add_development_dependency "sqlite3"
|
53
|
+
spec.metadata["rubygems_mfa_required"] = "true"
|
55
54
|
end
|
metadata
CHANGED
@@ -1,17 +1,17 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lite-command
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Juan Gomez
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-09-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: activemodel
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
@@ -25,7 +25,7 @@ dependencies:
|
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: ostruct
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - ">="
|
@@ -38,20 +38,6 @@ dependencies:
|
|
38
38
|
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
|
-
- !ruby/object:Gem::Dependency
|
42
|
-
name: activerecord
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - ">="
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: '0'
|
48
|
-
type: :development
|
49
|
-
prerelease: false
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
51
|
-
requirements:
|
52
|
-
- - ">="
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
version: '0'
|
55
41
|
- !ruby/object:Gem::Dependency
|
56
42
|
name: bundler
|
57
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -66,20 +52,6 @@ dependencies:
|
|
66
52
|
- - ">="
|
67
53
|
- !ruby/object:Gem::Version
|
68
54
|
version: '0'
|
69
|
-
- !ruby/object:Gem::Dependency
|
70
|
-
name: database_cleaner
|
71
|
-
requirement: !ruby/object:Gem::Requirement
|
72
|
-
requirements:
|
73
|
-
- - ">="
|
74
|
-
- !ruby/object:Gem::Version
|
75
|
-
version: '0'
|
76
|
-
type: :development
|
77
|
-
prerelease: false
|
78
|
-
version_requirements: !ruby/object:Gem::Requirement
|
79
|
-
requirements:
|
80
|
-
- - ">="
|
81
|
-
- !ruby/object:Gem::Version
|
82
|
-
version: '0'
|
83
55
|
- !ruby/object:Gem::Dependency
|
84
56
|
name: fasterer
|
85
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -233,20 +205,19 @@ files:
|
|
233
205
|
- lib/generators/rails/command_generator.rb
|
234
206
|
- lib/generators/rails/templates/command.rb.tt
|
235
207
|
- lib/lite/command.rb
|
236
|
-
- lib/lite/command/
|
237
|
-
- lib/lite/command/
|
238
|
-
- lib/lite/command/
|
239
|
-
- lib/lite/command/
|
240
|
-
- lib/lite/command/
|
241
|
-
- lib/lite/command/
|
242
|
-
- lib/lite/command/simple.rb
|
243
|
-
- lib/lite/command/states.rb
|
208
|
+
- lib/lite/command/base.rb
|
209
|
+
- lib/lite/command/context.rb
|
210
|
+
- lib/lite/command/fault.rb
|
211
|
+
- lib/lite/command/internals/callable.rb
|
212
|
+
- lib/lite/command/internals/executable.rb
|
213
|
+
- lib/lite/command/internals/resultable.rb
|
244
214
|
- lib/lite/command/version.rb
|
245
215
|
- lite-command.gemspec
|
246
216
|
homepage: http://drexed.github.io/lite-command
|
247
217
|
licenses:
|
248
218
|
- MIT
|
249
|
-
metadata:
|
219
|
+
metadata:
|
220
|
+
rubygems_mfa_required: 'true'
|
250
221
|
post_install_message:
|
251
222
|
rdoc_options: []
|
252
223
|
require_paths:
|
@@ -262,7 +233,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
262
233
|
- !ruby/object:Gem::Version
|
263
234
|
version: '0'
|
264
235
|
requirements: []
|
265
|
-
rubygems_version: 3.
|
236
|
+
rubygems_version: 3.5.19
|
266
237
|
signing_key:
|
267
238
|
specification_version: 4
|
268
239
|
summary: Ruby Command based framework (aka service objects)
|
data/lib/lite/command/complex.rb
DELETED
@@ -1,50 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Lite
|
4
|
-
module Command
|
5
|
-
class Complex
|
6
|
-
|
7
|
-
class << self
|
8
|
-
|
9
|
-
def call(*args, **kwargs, &block)
|
10
|
-
klass = new(*args, **kwargs, &block)
|
11
|
-
raise Lite::Command::NotImplementedError unless klass.respond_to?(:execute)
|
12
|
-
|
13
|
-
klass.call
|
14
|
-
klass
|
15
|
-
end
|
16
|
-
|
17
|
-
def execute(*args, **kwargs, &block)
|
18
|
-
klass = call(*args, **kwargs, &block)
|
19
|
-
klass.result
|
20
|
-
end
|
21
|
-
|
22
|
-
end
|
23
|
-
|
24
|
-
attr_reader :args, :result
|
25
|
-
|
26
|
-
def initialize(*args)
|
27
|
-
@args = args
|
28
|
-
end
|
29
|
-
|
30
|
-
def call
|
31
|
-
raise Lite::Command::NotImplementedError unless defined?(execute)
|
32
|
-
return @result if called?
|
33
|
-
|
34
|
-
@called = true
|
35
|
-
@result = execute
|
36
|
-
end
|
37
|
-
|
38
|
-
def called?
|
39
|
-
@called ||= false
|
40
|
-
end
|
41
|
-
|
42
|
-
def recall!
|
43
|
-
@called = false
|
44
|
-
%i[cache errors].each { |mixin| send(mixin).clear if respond_to?(mixin) }
|
45
|
-
call
|
46
|
-
end
|
47
|
-
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
@@ -1,88 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'lite/errors' unless defined?(Lite::Errors)
|
4
|
-
|
5
|
-
module Lite
|
6
|
-
module Command
|
7
|
-
module Extensions
|
8
|
-
module Errors
|
9
|
-
|
10
|
-
module ClassMethods
|
11
|
-
|
12
|
-
def perform(*args, **kwargs, &block)
|
13
|
-
klass = call(*args, **kwargs, &block)
|
14
|
-
|
15
|
-
if klass.success?
|
16
|
-
yield(klass.result, Lite::Command::Success, Lite::Command::Failure)
|
17
|
-
else
|
18
|
-
yield(klass.result, Lite::Command::Failure, Lite::Command::Success)
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
end
|
23
|
-
|
24
|
-
class << self
|
25
|
-
|
26
|
-
def included(klass)
|
27
|
-
klass.extend(ClassMethods)
|
28
|
-
end
|
29
|
-
|
30
|
-
end
|
31
|
-
|
32
|
-
def errors
|
33
|
-
@errors ||= Lite::Errors::Messages.new
|
34
|
-
end
|
35
|
-
|
36
|
-
def errored?
|
37
|
-
!errors.empty?
|
38
|
-
end
|
39
|
-
|
40
|
-
def fail!
|
41
|
-
raise Lite::Command::ValidationError
|
42
|
-
end
|
43
|
-
|
44
|
-
def failure?
|
45
|
-
called? && errored?
|
46
|
-
end
|
47
|
-
|
48
|
-
def merge_errors!(klass, direction: :from)
|
49
|
-
case direction
|
50
|
-
when :from then errors.merge!(klass.errors)
|
51
|
-
when :to then klass.errors.merge!(errors)
|
52
|
-
end
|
53
|
-
|
54
|
-
nil
|
55
|
-
end
|
56
|
-
|
57
|
-
def merge_exception!(exception, key: :internal)
|
58
|
-
errors.add(key, "#{exception.class} - #{exception.message}")
|
59
|
-
|
60
|
-
nil
|
61
|
-
end
|
62
|
-
|
63
|
-
def result!
|
64
|
-
result if valid?
|
65
|
-
end
|
66
|
-
|
67
|
-
def status
|
68
|
-
return :pending unless called?
|
69
|
-
|
70
|
-
success? ? :success : :failure
|
71
|
-
end
|
72
|
-
|
73
|
-
def success?
|
74
|
-
called? && !errored?
|
75
|
-
end
|
76
|
-
|
77
|
-
def validate!
|
78
|
-
return true if success?
|
79
|
-
|
80
|
-
fail!
|
81
|
-
end
|
82
|
-
|
83
|
-
alias valid? validate!
|
84
|
-
|
85
|
-
end
|
86
|
-
end
|
87
|
-
end
|
88
|
-
end
|