composable_operations 0.9.2 → 0.10.0
Sign up to get free protection for your applications and to get access to all the features.
- 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:
|