lite-command 1.5.0 → 2.0.1
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 -4
- data/CHANGELOG.md +8 -0
- data/Gemfile +1 -1
- data/Gemfile.lock +124 -100
- data/README.md +85 -231
- 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 +27 -29
- metadata +12 -55
- data/lib/lite/command/complex.rb +0 -52
- data/lib/lite/command/exceptions.rb +0 -10
- 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,53 @@
|
|
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 'lite-memoize'
|
40
|
+
spec.add_dependency "ostruct"
|
42
41
|
|
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'
|
42
|
+
spec.add_development_dependency "bundler"
|
43
|
+
spec.add_development_dependency "fasterer"
|
44
|
+
spec.add_development_dependency "generator_spec"
|
45
|
+
spec.add_development_dependency "rake"
|
46
|
+
spec.add_development_dependency "rspec"
|
47
|
+
spec.add_development_dependency "rubocop"
|
48
|
+
spec.add_development_dependency "rubocop-performance"
|
49
|
+
spec.add_development_dependency "rubocop-rake"
|
50
|
+
spec.add_development_dependency "rubocop-rspec"
|
51
|
+
spec.add_development_dependency "sqlite3"
|
52
|
+
spec.metadata["rubygems_mfa_required"] = "true"
|
55
53
|
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.1
|
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: ostruct
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
@@ -24,34 +24,6 @@ dependencies:
|
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: lite-memoize
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - ">="
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: '0'
|
34
|
-
type: :runtime
|
35
|
-
prerelease: false
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
37
|
-
requirements:
|
38
|
-
- - ">="
|
39
|
-
- !ruby/object:Gem::Version
|
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
27
|
- !ruby/object:Gem::Dependency
|
56
28
|
name: bundler
|
57
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -66,20 +38,6 @@ dependencies:
|
|
66
38
|
- - ">="
|
67
39
|
- !ruby/object:Gem::Version
|
68
40
|
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
41
|
- !ruby/object:Gem::Dependency
|
84
42
|
name: fasterer
|
85
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -233,20 +191,19 @@ files:
|
|
233
191
|
- lib/generators/rails/command_generator.rb
|
234
192
|
- lib/generators/rails/templates/command.rb.tt
|
235
193
|
- 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
|
194
|
+
- lib/lite/command/base.rb
|
195
|
+
- lib/lite/command/context.rb
|
196
|
+
- lib/lite/command/fault.rb
|
197
|
+
- lib/lite/command/internals/callable.rb
|
198
|
+
- lib/lite/command/internals/executable.rb
|
199
|
+
- lib/lite/command/internals/resultable.rb
|
244
200
|
- lib/lite/command/version.rb
|
245
201
|
- lite-command.gemspec
|
246
202
|
homepage: http://drexed.github.io/lite-command
|
247
203
|
licenses:
|
248
204
|
- MIT
|
249
|
-
metadata:
|
205
|
+
metadata:
|
206
|
+
rubygems_mfa_required: 'true'
|
250
207
|
post_install_message:
|
251
208
|
rdoc_options: []
|
252
209
|
require_paths:
|
@@ -262,7 +219,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
262
219
|
- !ruby/object:Gem::Version
|
263
220
|
version: '0'
|
264
221
|
requirements: []
|
265
|
-
rubygems_version: 3.
|
222
|
+
rubygems_version: 3.5.19
|
266
223
|
signing_key:
|
267
224
|
specification_version: 4
|
268
225
|
summary: Ruby Command based framework (aka service objects)
|
data/lib/lite/command/complex.rb
DELETED
@@ -1,52 +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
|
-
instance = new(*args, **kwargs, &block)
|
11
|
-
|
12
|
-
raise Lite::Command::NotImplementedError unless instance.respond_to?(:execute)
|
13
|
-
|
14
|
-
instance.call
|
15
|
-
instance
|
16
|
-
end
|
17
|
-
|
18
|
-
def execute(*args, **kwargs, &block)
|
19
|
-
instance = call(*args, **kwargs, &block)
|
20
|
-
instance.result
|
21
|
-
end
|
22
|
-
|
23
|
-
end
|
24
|
-
|
25
|
-
attr_reader :args, :result
|
26
|
-
|
27
|
-
def initialize(*args)
|
28
|
-
@args = args
|
29
|
-
end
|
30
|
-
|
31
|
-
def call
|
32
|
-
raise Lite::Command::NotImplementedError unless defined?(execute)
|
33
|
-
|
34
|
-
return @result if called?
|
35
|
-
|
36
|
-
@called = true
|
37
|
-
@result = execute
|
38
|
-
end
|
39
|
-
|
40
|
-
def called?
|
41
|
-
@called ||= false
|
42
|
-
end
|
43
|
-
|
44
|
-
def recall!
|
45
|
-
@called = false
|
46
|
-
%i[cache errors].each { |method_name| send(method_name).clear if respond_to?(method_name) }
|
47
|
-
call
|
48
|
-
end
|
49
|
-
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|