composable_operations 0.9.2 → 0.10.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/composable_operations.gemspec +1 -1
- data/lib/composable_operations/composed_operation.rb +10 -4
- data/lib/composable_operations/operation.rb +21 -11
- data/lib/composable_operations/version.rb +1 -1
- data/spec/composable_operations/composed_operation_spec.rb +34 -4
- data/spec/composable_operations/operation_input_processing_spec.rb +11 -23
- data/spec/composable_operations/operation_spec.rb +6 -4
- metadata +6 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 16bacd4b97dcd28f11356d7a01dbc3957487b5a9
|
4
|
+
data.tar.gz: f622ff84700dccf7ed5fc89d99907706b124e0b5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4a2bf743f4f0f86f5ab3f0c8265c68feedf626dbf76cf00c860184ae81e37dd4635a324adf46c9c4f0b7c90af675863ada47bcb0d12f732d4d47180e9683be57
|
7
|
+
data.tar.gz: 13dd02a2bdd146fab5bc27a265cf24a5180087303981c89b2aa23d89076a7fab70687be56971a6a63f6d8d78727267bb833b5080ec432776bed055963110eba7
|
@@ -19,7 +19,7 @@ multiple of these operations in operation pipelines.}
|
|
19
19
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
20
20
|
spec.require_paths = ["lib"]
|
21
21
|
|
22
|
-
spec.add_dependency "smart_properties", "~> 1.
|
22
|
+
spec.add_dependency "smart_properties", "~> 1.10"
|
23
23
|
|
24
24
|
spec.add_development_dependency "bundler", "~> 1.3"
|
25
25
|
spec.add_development_dependency "pry", "~> 0.9.0"
|
@@ -8,8 +8,9 @@ module ComposableOperations
|
|
8
8
|
@_options = options
|
9
9
|
end
|
10
10
|
|
11
|
-
def
|
12
|
-
|
11
|
+
def new(context, *input)
|
12
|
+
input = input.shift(arity)
|
13
|
+
__getobj__.new *input, Hash[Array(@_options).map do |key, value|
|
13
14
|
[key, value.kind_of?(Proc) ? context.instance_exec(&value) : value]
|
14
15
|
end]
|
15
16
|
end
|
@@ -23,6 +24,11 @@ module ComposableOperations
|
|
23
24
|
end
|
24
25
|
|
25
26
|
def use(operation, options = {})
|
27
|
+
if operations.empty?
|
28
|
+
arguments = operation.arguments
|
29
|
+
processes(*arguments) unless arguments.empty?
|
30
|
+
end
|
31
|
+
|
26
32
|
(@operations ||= []) << OperationFactory.new(operation, options)
|
27
33
|
end
|
28
34
|
|
@@ -47,9 +53,9 @@ module ComposableOperations
|
|
47
53
|
def execute
|
48
54
|
self.class.operations.inject(input) do |data, operation|
|
49
55
|
operation = if data.respond_to?(:to_ary)
|
50
|
-
operation.
|
56
|
+
operation.new(self, *data)
|
51
57
|
else
|
52
|
-
operation.
|
58
|
+
operation.new(self, data)
|
53
59
|
end
|
54
60
|
operation.perform
|
55
61
|
|
@@ -4,11 +4,14 @@ module ComposableOperations
|
|
4
4
|
include SmartProperties
|
5
5
|
|
6
6
|
class << self
|
7
|
+
attr_writer :arguments
|
7
8
|
|
8
|
-
|
9
|
+
def arguments
|
10
|
+
@arguments ||= []
|
11
|
+
end
|
9
12
|
|
10
13
|
def arity
|
11
|
-
|
14
|
+
arguments.count
|
12
15
|
end
|
13
16
|
|
14
17
|
def perform(*args)
|
@@ -57,15 +60,13 @@ module ComposableOperations
|
|
57
60
|
end
|
58
61
|
|
59
62
|
def processes(*names)
|
60
|
-
self.arity = names.length
|
61
|
-
|
62
63
|
case names.length
|
63
64
|
when 0
|
64
65
|
raise ArgumentError, "#{self}.#{__callee__} expects at least one argument"
|
65
66
|
else
|
66
67
|
names.each_with_index do |name, index|
|
67
|
-
|
68
|
-
|
68
|
+
property(name, required: true) unless properties.key?(name)
|
69
|
+
arguments << name
|
69
70
|
end
|
70
71
|
end
|
71
72
|
end
|
@@ -90,12 +91,21 @@ module ComposableOperations
|
|
90
91
|
attr_reader :exception
|
91
92
|
|
92
93
|
def initialize(*args)
|
93
|
-
|
94
|
-
|
95
|
-
|
94
|
+
arity = self.class.arity
|
95
|
+
arguments = args.shift(arity)
|
96
|
+
attributes = args.last.kind_of?(Hash) ? args.pop : {}
|
97
|
+
|
98
|
+
raise ArgumentError, "wrong number of arguments #{arguments.length + args.length} for #{arity}" unless args.empty?
|
99
|
+
|
100
|
+
self.class.arguments.each_with_index do |name, index|
|
101
|
+
attributes[name] = arguments[index]
|
102
|
+
end
|
103
|
+
|
104
|
+
super(attributes)
|
105
|
+
end
|
96
106
|
|
97
|
-
|
98
|
-
|
107
|
+
def input
|
108
|
+
self.class.arguments.map { |name| self[name] }
|
99
109
|
end
|
100
110
|
|
101
111
|
def failed?
|
@@ -29,6 +29,7 @@ describe ComposableOperations::ComposedOperation do
|
|
29
29
|
|
30
30
|
let(:string_multiplier) do
|
31
31
|
Class.new(ComposableOperations::Operation) do
|
32
|
+
processes :text
|
32
33
|
property :multiplicator, default: 1, converts: :to_i, required: true
|
33
34
|
property :separator, default: ' ', converts: :to_s, required: true
|
34
35
|
|
@@ -37,20 +38,24 @@ describe ComposableOperations::ComposedOperation do
|
|
37
38
|
end
|
38
39
|
|
39
40
|
def execute
|
40
|
-
(Array(
|
41
|
+
(Array(text) * multiplicator).join(separator)
|
41
42
|
end
|
42
43
|
end
|
43
44
|
end
|
44
45
|
|
45
46
|
let(:halting_operation) do
|
46
47
|
Class.new(ComposableOperations::Operation) do
|
48
|
+
def self.name
|
49
|
+
"HaltingOperation"
|
50
|
+
end
|
51
|
+
|
47
52
|
def execute
|
48
53
|
halt
|
49
54
|
end
|
50
55
|
end
|
51
56
|
end
|
52
57
|
|
53
|
-
context "when composed of one operation that generates
|
58
|
+
context "when composed of one operation that generates" do
|
54
59
|
subject(:composed_operation) do
|
55
60
|
operation = string_generator
|
56
61
|
|
@@ -60,7 +65,7 @@ describe ComposableOperations::ComposedOperation do
|
|
60
65
|
end
|
61
66
|
|
62
67
|
it "should return this string as result" do
|
63
|
-
expect(composed_operation.perform
|
68
|
+
expect(composed_operation.perform).to eq("chunky bacon")
|
64
69
|
end
|
65
70
|
end
|
66
71
|
|
@@ -100,7 +105,7 @@ describe ComposableOperations::ComposedOperation do
|
|
100
105
|
end
|
101
106
|
|
102
107
|
it "should return a capitalized version of the generated string" do
|
103
|
-
expect(composed_operation.perform
|
108
|
+
expect(composed_operation.perform).to eq("CHUNKY BACON")
|
104
109
|
end
|
105
110
|
|
106
111
|
it { is_expected.to utilize_operations(string_generator, string_capitalizer) }
|
@@ -123,5 +128,30 @@ describe ComposableOperations::ComposedOperation do
|
|
123
128
|
end
|
124
129
|
it { is_expected.to utilize_operations(string_generator, halting_operation, string_capitalizer) }
|
125
130
|
end
|
131
|
+
|
132
|
+
context "when composed of two operations; one that that capitalizes a string and one that repeats the string" do
|
133
|
+
subject(:composed_operation) do
|
134
|
+
operations = [string_capitalizer, string_multiplier]
|
135
|
+
|
136
|
+
Class.new(described_class) do
|
137
|
+
use operations.first
|
138
|
+
use operations.last, multiplicator: 2
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
it "should raise when instantiated with no input" do
|
143
|
+
expect { composed_operation.new }.to raise_error(ArgumentError)
|
144
|
+
end
|
145
|
+
|
146
|
+
it "should not raise when instantiated with a string" do
|
147
|
+
expect { composed_operation.new("some string") }.to_not raise_error
|
148
|
+
end
|
149
|
+
|
150
|
+
it "should have an input argument with the same name as the first operation" do
|
151
|
+
expect(composed_operation.arguments).to eq(string_capitalizer.arguments)
|
152
|
+
end
|
153
|
+
|
154
|
+
it { is_expected.to succeed_to_perform.when_initialized_with("hello").and_return("HELLO HELLO") }
|
155
|
+
end
|
126
156
|
end
|
127
157
|
|
@@ -16,19 +16,6 @@ describe ComposableOperations::Operation, "input processing:" do
|
|
16
16
|
it { is_expected.to succeed_to_perform.when_initialized_with(input).and_return(input) }
|
17
17
|
end
|
18
18
|
|
19
|
-
describe "An operation that takes no arguments except for a Hash of additional options" do
|
20
|
-
subject(:operation) do
|
21
|
-
Class.new(described_class) do
|
22
|
-
def execute
|
23
|
-
input
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
it { is_expected.to succeed_to_perform.when_initialized_with(key: :value).and_return([]) }
|
29
|
-
it { is_expected.to succeed_to_perform.when_initialized_with(1, 2, 3, key: :value).and_return([1, 2, 3]) }
|
30
|
-
end
|
31
|
-
|
32
19
|
describe "An operation that takes a Hash as input and an Hash of additional options" do
|
33
20
|
let(:input) { { food: nil } }
|
34
21
|
|
@@ -71,7 +58,6 @@ describe ComposableOperations::Operation, "input processing:" do
|
|
71
58
|
end
|
72
59
|
|
73
60
|
it { is_expected.to succeed_to_perform.when_initialized_with(1, 2).and_return([1, 2]) }
|
74
|
-
it { is_expected.to succeed_to_perform.when_initialized_with(1, 2, 3).and_return([1, 2, 3]) }
|
75
61
|
end
|
76
62
|
|
77
63
|
describe "An operation that takes multiple arguments as input where the last of these arguments is a Hash" do
|
@@ -89,31 +75,33 @@ describe ComposableOperations::Operation, "input processing:" do
|
|
89
75
|
it { is_expected.to succeed_to_perform.when_initialized_with(1, 2, operator: :*).and_return(2) }
|
90
76
|
end
|
91
77
|
|
92
|
-
describe "An operation that takes
|
78
|
+
describe "An operation that takes a named argument and uses the setter for the named argument" do
|
93
79
|
subject(:operation) do
|
94
80
|
Class.new(described_class) do
|
95
|
-
processes :some_value
|
81
|
+
processes :some_value
|
96
82
|
def execute
|
97
|
-
|
83
|
+
self.some_value = "changed"
|
84
|
+
self.some_value
|
98
85
|
end
|
99
86
|
end
|
100
87
|
end
|
101
88
|
|
102
|
-
it { is_expected.to succeed_to_perform.when_initialized_with(
|
89
|
+
it { is_expected.to succeed_to_perform.when_initialized_with("unchanged").and_return("changed") }
|
103
90
|
end
|
104
91
|
|
105
|
-
describe "An operation that
|
92
|
+
describe "An operation that manually defines a property for its first input argument that upcases its assgined value" do
|
106
93
|
subject(:operation) do
|
107
94
|
Class.new(described_class) do
|
108
|
-
|
95
|
+
property :text, converts: :upcase
|
96
|
+
processes :text
|
97
|
+
|
109
98
|
def execute
|
110
|
-
|
111
|
-
self.some_value
|
99
|
+
text
|
112
100
|
end
|
113
101
|
end
|
114
102
|
end
|
115
103
|
|
116
|
-
it { is_expected.to succeed_to_perform.when_initialized_with("
|
104
|
+
it { is_expected.to succeed_to_perform.when_initialized_with("hello").and_return("HELLO") }
|
117
105
|
end
|
118
106
|
end
|
119
107
|
|
@@ -2,28 +2,30 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe ComposableOperations::Operation do
|
4
4
|
context "that always returns nil when executed" do
|
5
|
-
|
6
|
-
|
5
|
+
let(:nil_operation) do
|
6
|
+
Class.new(described_class) do
|
7
7
|
def execute
|
8
8
|
nil
|
9
9
|
end
|
10
10
|
end
|
11
|
-
operation
|
12
11
|
end
|
13
12
|
|
13
|
+
subject { nil_operation.new }
|
14
|
+
|
14
15
|
it { is_expected.to succeed_to_perform.and_return(nil) }
|
15
16
|
end
|
16
17
|
|
17
18
|
context "that always halts and returns its original input" do
|
18
19
|
let(:halting_operation) do
|
19
20
|
Class.new(described_class) do
|
21
|
+
processes :message
|
20
22
|
def execute
|
21
23
|
halt "Full stop!", input.first
|
22
24
|
end
|
23
25
|
end
|
24
26
|
end
|
25
27
|
|
26
|
-
|
28
|
+
subject(:halting_operation_instance) do
|
27
29
|
halting_operation.new("Test")
|
28
30
|
end
|
29
31
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: composable_operations
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.10.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Konstantin Tennhard
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2015-10-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: smart_properties
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '1.
|
19
|
+
version: '1.10'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '1.
|
26
|
+
version: '1.10'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: bundler
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -131,7 +131,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
131
131
|
version: '0'
|
132
132
|
requirements: []
|
133
133
|
rubyforge_project:
|
134
|
-
rubygems_version: 2.
|
134
|
+
rubygems_version: 2.4.5
|
135
135
|
signing_key:
|
136
136
|
specification_version: 4
|
137
137
|
summary: Tool set for operation pipelines.
|
@@ -143,3 +143,4 @@ test_files:
|
|
143
143
|
- spec/composable_operations/operation_input_processing_spec.rb
|
144
144
|
- spec/composable_operations/operation_spec.rb
|
145
145
|
- spec/spec_helper.rb
|
146
|
+
has_rdoc:
|