riker 0.1.0.pre4 → 0.1.0.pre6
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/Gemfile +1 -0
- data/Gemfile.lock +7 -1
- data/README.md +60 -1
- data/lib/riker/command/fallible_methods.rb +23 -0
- data/lib/riker/command/function_writer.rb +14 -0
- data/lib/riker/command/parameters.rb +6 -0
- data/lib/riker/command/run_bang_function.rb +36 -4
- data/lib/riker/command/run_function.rb +59 -0
- data/lib/riker/command.rb +4 -0
- data/lib/riker/outcome/errors.rb +48 -0
- data/lib/riker/outcome/execution_error.rb +24 -0
- data/lib/riker/outcome.rb +61 -0
- data/lib/riker/version.rb +1 -1
- data/lib/riker.rb +11 -0
- metadata +7 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bd22e31d55bf8c4144736d6b657463e2550b8a602711adfcc4e8339a164d16c6
|
4
|
+
data.tar.gz: 83b5819f498d4f86f89531f81df7ca845540b108a5cac03274a0fc9d9f0b1ede
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7777cf030f8bf79ceaabd4da1a826b32be8cfcc8be0f32b262d1219839dd1268d24596ad3d83320d5eb6da2f15eb9dd31a870ef3f3d12eea53eec61f8bd27982
|
7
|
+
data.tar.gz: 818646ea533fefd5fe79580127585ed365af10352ee0f467aa84017a967a6afcdb0ed639f3933fc6c371bd0535b57c8d156b9b6d5066f32ea168e2372ed9bfbe
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,17 +1,22 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
riker (0.1.0.
|
4
|
+
riker (0.1.0.pre5)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: https://rubygems.org/
|
8
8
|
specs:
|
9
9
|
ast (2.4.2)
|
10
|
+
coderay (1.1.3)
|
10
11
|
diff-lcs (1.5.0)
|
11
12
|
json (2.6.2)
|
13
|
+
method_source (1.0.0)
|
12
14
|
parallel (1.22.1)
|
13
15
|
parser (3.1.2.1)
|
14
16
|
ast (~> 2.4.1)
|
17
|
+
pry (0.14.1)
|
18
|
+
coderay (~> 1.1)
|
19
|
+
method_source (~> 1.0)
|
15
20
|
rainbow (3.1.1)
|
16
21
|
rake (13.0.6)
|
17
22
|
regexp_parser (2.5.0)
|
@@ -49,6 +54,7 @@ PLATFORMS
|
|
49
54
|
x86_64-linux
|
50
55
|
|
51
56
|
DEPENDENCIES
|
57
|
+
pry (~> 0.14)
|
52
58
|
rake (~> 13.0)
|
53
59
|
riker!
|
54
60
|
rspec (~> 3.0)
|
data/README.md
CHANGED
@@ -12,7 +12,7 @@ High-Performance, Dependency-Free Command Pattern For Ruby
|
|
12
12
|
### In your gemfile:
|
13
13
|
|
14
14
|
```ruby
|
15
|
-
gem 'riker', '0.1.0.
|
15
|
+
gem 'riker', '0.1.0.pre6'
|
16
16
|
```
|
17
17
|
|
18
18
|
### In your code:
|
@@ -26,6 +26,11 @@ class SimpleGreeting
|
|
26
26
|
param :punctuation, default: '.'
|
27
27
|
|
28
28
|
execute do
|
29
|
+
if first_name == 'Voldemort'
|
30
|
+
errors.add(:first_name, 'He who shall not be named!')
|
31
|
+
return
|
32
|
+
end
|
33
|
+
|
29
34
|
return "Hello #{first_name}#{punctuation}" if last_name.nil?
|
30
35
|
|
31
36
|
"Hello #{first_name} #{last_name}#{punctuation}"
|
@@ -44,6 +49,24 @@ SimpleGreeting.run!(first_name: 'Will', last_name: 'Riker')
|
|
44
49
|
|
45
50
|
SimpleGreeting.run!(first_name: 'Will', last_name: 'Riker', punctuation: '!')
|
46
51
|
# => "Hello Will Riker!"
|
52
|
+
|
53
|
+
SimpleGreeting.run!(first_name: 'Voldemort')
|
54
|
+
# => Riker::Outcome::ExecutionError => e
|
55
|
+
# => e.errors.messages == ['He who shall not be named!']
|
56
|
+
|
57
|
+
outcome = SimpleGreeting.run(first_name: 'Will')
|
58
|
+
outcome.valid?
|
59
|
+
# => true
|
60
|
+
outcome.result
|
61
|
+
# => "Hello Will."
|
62
|
+
|
63
|
+
outcome = SimpleGreeting.run(first_name: 'Voldemort')
|
64
|
+
outcome.invalid?
|
65
|
+
# => true
|
66
|
+
outcome.result
|
67
|
+
# => nil
|
68
|
+
outcome.errors.messages
|
69
|
+
# => ['He who shall not be named!']
|
47
70
|
```
|
48
71
|
|
49
72
|
## Default Procs
|
@@ -72,3 +95,39 @@ CaptainsLog.run!(message: "The Borg are attacking!")
|
|
72
95
|
CaptainsLog.run(message: "We've traveled back in time!", stardate: 42.1337)
|
73
96
|
# => "Captain's Log; Stardate: 42.1337\n\nWe've traveled back in time!"
|
74
97
|
```
|
98
|
+
|
99
|
+
## Measurement Code
|
100
|
+
|
101
|
+
Sometimes you'll want to do some logic around your commands to record
|
102
|
+
their performance, number of calls, etc. Rike allows for this with `around`.
|
103
|
+
The result of your measurement code in no way effects the result from
|
104
|
+
the command.
|
105
|
+
|
106
|
+
```ruby
|
107
|
+
module SensorArray
|
108
|
+
class << self
|
109
|
+
# the class and args of the command are provided
|
110
|
+
def deep_scan(klass, args)
|
111
|
+
# anything before code runs
|
112
|
+
|
113
|
+
# code runs here
|
114
|
+
yield
|
115
|
+
|
116
|
+
# anything after you want
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
class CheckWarpDrive
|
122
|
+
extend Riker
|
123
|
+
|
124
|
+
param :stardate
|
125
|
+
param :engineer
|
126
|
+
|
127
|
+
around &SensorArray.method(:deep_scan)
|
128
|
+
|
129
|
+
execute do
|
130
|
+
"WarpDrive checked by #{engineer} on #{stardate}"
|
131
|
+
end
|
132
|
+
end
|
133
|
+
```
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Riker
|
4
|
+
class Command
|
5
|
+
# Fallible Methods
|
6
|
+
#
|
7
|
+
# Every command has fallible functionality. This is
|
8
|
+
# how you can convey something has gone wrong to the
|
9
|
+
# caller of your command.
|
10
|
+
#
|
11
|
+
module FallibleMethods
|
12
|
+
# @return [Riker::Outcome::Errors]
|
13
|
+
def errors
|
14
|
+
@errors ||= Riker::Outcome::Errors.new
|
15
|
+
end
|
16
|
+
|
17
|
+
# @return [Boolean]
|
18
|
+
def errored?
|
19
|
+
defined?(@errors) && @errors.any?
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require_relative 'run_bang_function'
|
4
4
|
require_relative 'initialize_function'
|
5
|
+
require_relative 'run_function'
|
5
6
|
|
6
7
|
module Riker
|
7
8
|
class Command
|
@@ -13,9 +14,14 @@ module Riker
|
|
13
14
|
class FunctionWriter
|
14
15
|
DEFAULT_FUNCTIONS = [
|
15
16
|
RunBangFunction,
|
17
|
+
RunFunction,
|
16
18
|
InitializeFunction
|
17
19
|
].freeze
|
18
20
|
|
21
|
+
INSTANCE_METHOD_MODULES = [
|
22
|
+
FallibleMethods
|
23
|
+
].freeze
|
24
|
+
|
19
25
|
# @return [Riker::Command]
|
20
26
|
attr_reader :command
|
21
27
|
|
@@ -34,6 +40,7 @@ module Riker
|
|
34
40
|
define_default_setters!(klass)
|
35
41
|
define_attr_readers!(klass)
|
36
42
|
write_functions!(klass)
|
43
|
+
include_instance_methods!(klass)
|
37
44
|
end
|
38
45
|
|
39
46
|
private
|
@@ -57,6 +64,13 @@ module Riker
|
|
57
64
|
param.default.build_default_function!(klass)
|
58
65
|
end
|
59
66
|
end
|
67
|
+
|
68
|
+
# @param klass [Class]
|
69
|
+
def include_instance_methods!(klass)
|
70
|
+
INSTANCE_METHOD_MODULES.each do |mod|
|
71
|
+
klass.include(mod)
|
72
|
+
end
|
73
|
+
end
|
60
74
|
end
|
61
75
|
end
|
62
76
|
end
|
@@ -12,6 +12,11 @@ module Riker
|
|
12
12
|
include Enumerable
|
13
13
|
class ParamNameTaken < ::Riker::Error; end
|
14
14
|
class InvalidParamName < ::Riker::Error; end
|
15
|
+
class ReservedAttributeName < ::Riker::Error; end
|
16
|
+
|
17
|
+
RESERVED_ATTR_NAMES = %i[
|
18
|
+
errors
|
19
|
+
].to_set.freeze
|
15
20
|
|
16
21
|
def initialize
|
17
22
|
# @var [Hash<Symbol, Parameter>]
|
@@ -47,6 +52,7 @@ module Riker
|
|
47
52
|
|
48
53
|
def validate_name!(name)
|
49
54
|
raise InvalidParamName unless name.is_a?(Symbol)
|
55
|
+
raise ReservedAttributeName if RESERVED_ATTR_NAMES.include?(name)
|
50
56
|
raise ParamNameTaken if @params.key?(name)
|
51
57
|
end
|
52
58
|
end
|
@@ -14,11 +14,43 @@ module Riker
|
|
14
14
|
|
15
15
|
# @return [Riker::Command::FunctionDetails]
|
16
16
|
def details
|
17
|
+
if command.around_block
|
18
|
+
with_around_function_block
|
19
|
+
else
|
20
|
+
without_around_block_function
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
# @return [Riker::Command::FunctionDetails]
|
27
|
+
def without_around_block_function
|
28
|
+
FunctionDetails.new(<<~RUBY, __FILE__, __LINE__ + 1)
|
29
|
+
def self.run!(**arguments) # def self.run!(**arguments)
|
30
|
+
command = new(**arguments) # command = new(**arguments)
|
31
|
+
result = command.execute # result = command.execute
|
32
|
+
if command.errored? # if command.errored?
|
33
|
+
command.errors.raise! # command.errors.raise!
|
34
|
+
end # end
|
35
|
+
result # result
|
36
|
+
end # end
|
37
|
+
RUBY
|
38
|
+
end
|
39
|
+
|
40
|
+
# @return [Riker::Command::FunctionDetails]
|
41
|
+
def with_around_function_block
|
17
42
|
FunctionDetails.new(<<~RUBY, __FILE__, __LINE__ + 1)
|
18
|
-
def self.run!(**arguments)
|
19
|
-
|
20
|
-
command.
|
21
|
-
|
43
|
+
def self.run!(**arguments) # def self.run!(**arguments)
|
44
|
+
result = nil # result = nil
|
45
|
+
self.command.around_block.call(self, arguments) do # self.command.around_block.call(klass, arguments) do
|
46
|
+
command = new(**arguments) # command = new(**arguments)
|
47
|
+
result = command.execute # result = command.execute
|
48
|
+
if command.errored? # if command.errored?
|
49
|
+
command.errors.raise! # command.errors.raise!
|
50
|
+
end # end
|
51
|
+
end # end
|
52
|
+
result # result
|
53
|
+
end # end
|
22
54
|
RUBY
|
23
55
|
end
|
24
56
|
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Riker
|
4
|
+
class Command
|
5
|
+
# Run!
|
6
|
+
#
|
7
|
+
# Represents the `run!` static method for your command
|
8
|
+
#
|
9
|
+
class RunFunction < Function
|
10
|
+
# @return [Symbol]
|
11
|
+
def name
|
12
|
+
:run
|
13
|
+
end
|
14
|
+
|
15
|
+
# @return [Riker::Command::FunctionDetails]
|
16
|
+
def details
|
17
|
+
if command.around_block
|
18
|
+
with_around_block_function
|
19
|
+
else
|
20
|
+
without_around_block_function
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def without_around_block_function
|
27
|
+
FunctionDetails.new(<<~RUBY, __FILE__, __LINE__ + 1)
|
28
|
+
def self.run(**arguments) # def self.run!(**arguments)
|
29
|
+
command = new(**arguments) # command = new(**arguments)
|
30
|
+
result = command.execute # result = command.execute
|
31
|
+
if command.errored? # if command.errored?
|
32
|
+
Riker::Outcome.invalid(command.errors) # Riker::Outcome.invalid(command.errors)
|
33
|
+
else # else
|
34
|
+
Riker::Outcome.valid(result) # Riker::Outcome.valid(result)
|
35
|
+
end # end
|
36
|
+
end # end
|
37
|
+
RUBY
|
38
|
+
end
|
39
|
+
|
40
|
+
def with_around_block_function
|
41
|
+
FunctionDetails.new(<<~RUBY, __FILE__, __LINE__ + 1)
|
42
|
+
def self.run(**arguments) # def self.run!(**arguments)
|
43
|
+
outcome = nil # outcome = nil
|
44
|
+
self.command.around_block.call(self, arguments) do # self.command.around_block.call(self, arguments) do
|
45
|
+
command = new(**arguments) # command = new(**arguments)
|
46
|
+
result = command.execute # result = command.execute
|
47
|
+
outcome = if command.errored? # outcome = if command.errored?
|
48
|
+
Riker::Outcome.invalid(command.errors) # Riker::Outcome.invalid(command.errors)
|
49
|
+
else # else
|
50
|
+
Riker::Outcome.valid(result) # Riker::Outcome.valid(result)
|
51
|
+
end # end
|
52
|
+
end # end
|
53
|
+
outcome # outcome
|
54
|
+
end # end
|
55
|
+
RUBY
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
data/lib/riker/command.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative 'command/parameters'
|
4
|
+
require_relative 'command/fallible_methods'
|
4
5
|
require_relative 'command/function'
|
5
6
|
require_relative 'command/function_details'
|
6
7
|
require_relative 'command/function_writer'
|
@@ -21,6 +22,9 @@ module Riker
|
|
21
22
|
# @return [Proc, nil]
|
22
23
|
attr_accessor :execute_block
|
23
24
|
|
25
|
+
# @return [Proc, nil]
|
26
|
+
attr_accessor :around_block
|
27
|
+
|
24
28
|
def initialize
|
25
29
|
@parameters = Parameters.new
|
26
30
|
@function_writer = FunctionWriter.new(self)
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Riker
|
4
|
+
class Outcome
|
5
|
+
# Outcome Errors
|
6
|
+
#
|
7
|
+
# A wrapper to keep track of and report on errors
|
8
|
+
# that happened during the execution of a command.
|
9
|
+
#
|
10
|
+
class Errors
|
11
|
+
# @!method any?
|
12
|
+
# @return [Boolean]
|
13
|
+
# @!method none?
|
14
|
+
# @return [Boolean]
|
15
|
+
extend Forwardable
|
16
|
+
def_delegators :@errors, :any?, :none?
|
17
|
+
|
18
|
+
def initialize
|
19
|
+
@errors = Hash.new { |hash, key| hash[key] = [] }
|
20
|
+
end
|
21
|
+
|
22
|
+
# @param key [Symbol]
|
23
|
+
# @param error [String]
|
24
|
+
# @return [void]
|
25
|
+
def add(key, error)
|
26
|
+
@errors[key] << error
|
27
|
+
|
28
|
+
nil
|
29
|
+
end
|
30
|
+
|
31
|
+
# @return [Array<String>]
|
32
|
+
def messages
|
33
|
+
@errors.values.flatten!
|
34
|
+
end
|
35
|
+
|
36
|
+
# @raise [Riker::ExecutionError]
|
37
|
+
def raise!
|
38
|
+
raise as_execution_error
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def as_execution_error
|
44
|
+
Riker::Outcome::ExecutionError.new(self)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Riker
|
4
|
+
class Outcome
|
5
|
+
# Execution Error
|
6
|
+
#
|
7
|
+
# This exception is raised when a problem has happened
|
8
|
+
# with your command. It is the result normall of having
|
9
|
+
# errors.
|
10
|
+
#
|
11
|
+
# @see Riker::Command::FallibleMethods
|
12
|
+
#
|
13
|
+
class ExecutionError < Error
|
14
|
+
# @return [Riker::Outcome::Errors]
|
15
|
+
attr_reader :errors
|
16
|
+
|
17
|
+
# @param errors [Riker::Outcome::Errors]
|
18
|
+
def initialize(errors)
|
19
|
+
super()
|
20
|
+
@errors = errors
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'outcome/errors'
|
4
|
+
require_relative 'outcome/execution_error'
|
5
|
+
|
6
|
+
module Riker
|
7
|
+
# Wrapped Outcome of a Command
|
8
|
+
#
|
9
|
+
# Commands may be fallible; and in that case
|
10
|
+
# they return an outcome that will either detail
|
11
|
+
# the errors that came up during execution or the
|
12
|
+
# expected data if it was success.
|
13
|
+
#
|
14
|
+
class Outcome
|
15
|
+
# @return [Object]
|
16
|
+
attr_reader :result
|
17
|
+
|
18
|
+
class << self
|
19
|
+
# @param result [Object]
|
20
|
+
# @return [Riker::Outcome]
|
21
|
+
def valid(result)
|
22
|
+
new(:valid, result)
|
23
|
+
end
|
24
|
+
|
25
|
+
def invalid(errors)
|
26
|
+
new(:invalid, errors)
|
27
|
+
end
|
28
|
+
|
29
|
+
private :new
|
30
|
+
end
|
31
|
+
|
32
|
+
# @param state [:valid, :invalid]
|
33
|
+
# @data [Object, Riker::Outcome::Errors]
|
34
|
+
def initialize(state, data)
|
35
|
+
if state == :valid
|
36
|
+
@result = data
|
37
|
+
else
|
38
|
+
@errors = data
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# @return [Boolean]
|
43
|
+
def valid?
|
44
|
+
return true unless defined?(@errors)
|
45
|
+
|
46
|
+
@errors.none?
|
47
|
+
end
|
48
|
+
|
49
|
+
# @return [Boolean]
|
50
|
+
def invalid?
|
51
|
+
return false unless defined?(@errors)
|
52
|
+
|
53
|
+
@errors.any?
|
54
|
+
end
|
55
|
+
|
56
|
+
# @return [Riker::Outcome::Errors]
|
57
|
+
def errors
|
58
|
+
@errors ||= Errors.new
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
data/lib/riker/version.rb
CHANGED
data/lib/riker.rb
CHANGED
@@ -1,9 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'forwardable'
|
4
|
+
require 'set'
|
5
|
+
|
3
6
|
require_relative 'riker/version'
|
4
7
|
require_relative 'riker/error'
|
5
8
|
require_relative 'riker/command'
|
6
9
|
require_relative 'riker/parameter'
|
10
|
+
require_relative 'riker/outcome'
|
7
11
|
|
8
12
|
# The Commander of the USS Enterprise
|
9
13
|
module Riker
|
@@ -27,4 +31,11 @@ module Riker
|
|
27
31
|
command.execute_block = block
|
28
32
|
command.function_writer.write!(self)
|
29
33
|
end
|
34
|
+
|
35
|
+
# @block the logic to run around a command
|
36
|
+
def around(&block)
|
37
|
+
raise Error, "around block already called for #{self}!" if command.around_block
|
38
|
+
|
39
|
+
command.around_block = block
|
40
|
+
end
|
30
41
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: riker
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.0.
|
4
|
+
version: 0.1.0.pre6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Benjamin Falk
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-11-01 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: High-Performance, Dependency-Free Command Pattern For Ruby
|
14
14
|
email:
|
@@ -29,13 +29,18 @@ files:
|
|
29
29
|
- bin/setup
|
30
30
|
- lib/riker.rb
|
31
31
|
- lib/riker/command.rb
|
32
|
+
- lib/riker/command/fallible_methods.rb
|
32
33
|
- lib/riker/command/function.rb
|
33
34
|
- lib/riker/command/function_details.rb
|
34
35
|
- lib/riker/command/function_writer.rb
|
35
36
|
- lib/riker/command/initialize_function.rb
|
36
37
|
- lib/riker/command/parameters.rb
|
37
38
|
- lib/riker/command/run_bang_function.rb
|
39
|
+
- lib/riker/command/run_function.rb
|
38
40
|
- lib/riker/error.rb
|
41
|
+
- lib/riker/outcome.rb
|
42
|
+
- lib/riker/outcome/errors.rb
|
43
|
+
- lib/riker/outcome/execution_error.rb
|
39
44
|
- lib/riker/parameter.rb
|
40
45
|
- lib/riker/parameter/default_value.rb
|
41
46
|
- lib/riker/version.rb
|