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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 237f6bf42a1d019c2f0de93dd8baa18c187fa276
4
- data.tar.gz: 1c8648513871178ab2d34127fa29b1799adbee28
3
+ metadata.gz: 16bacd4b97dcd28f11356d7a01dbc3957487b5a9
4
+ data.tar.gz: f622ff84700dccf7ed5fc89d99907706b124e0b5
5
5
  SHA512:
6
- metadata.gz: 1f241f35e8737eb4b1aa2a585921ec97d44ccaf62210d7eb9b166e74933cbfb8a9d147c6aee31d36bcf13fca4acf8475ed3bdcb3bde30aa9115bab8c91e645fd
7
- data.tar.gz: 483847be976d67e1afdcd24dd5a5cf28237a1598e4b1419de1ccb48dd623a318b1ec137b68688172d77c4ff6c17056c92dce1413a678bbf631258adb08270fdd
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.0"
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 create(context, *input)
12
- new *input, Hash[Array(@_options).map do |key, value|
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.create(self, *data)
56
+ operation.new(self, *data)
51
57
  else
52
- operation.create(self, data)
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
- attr_writer :arity
9
+ def arguments
10
+ @arguments ||= []
11
+ end
9
12
 
10
13
  def arity
11
- @arity || 0
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
- define_method(name) { input[index] }
68
- define_method("#{name}=") { |value| input[index] = value }
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
- named_input_parameters = args.shift(self.class.arity)
94
- options = args.last.kind_of?(Hash) ? args.pop : {}
95
- unnamed_input_parameters = args
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
- @input = named_input_parameters + unnamed_input_parameters
98
- super(options)
107
+ def input
108
+ self.class.arguments.map { |name| self[name] }
99
109
  end
100
110
 
101
111
  def failed?
@@ -1,3 +1,3 @@
1
1
  module ComposableOperations
2
- VERSION = "0.9.2"
2
+ VERSION = "0.10.0"
3
3
  end
@@ -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(input) * multiplicator).join(separator)
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 a string no matter the input" do
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(nil)).to eq("chunky bacon")
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(nil)).to eq("CHUNKY BACON")
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 multiple arguments as input where the last of these arguments is a Hash, as well as, a Hash of additional options" do
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, :yet_another_value, :a_hash
81
+ processes :some_value
96
82
  def execute
97
- a_hash
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(1, 2, {food: "chunky bacon"}, { additional: :options }).and_return(food: "chunky bacon") }
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 takes a named argument and uses the setter for the named argument" do
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
- processes :some_value
95
+ property :text, converts: :upcase
96
+ processes :text
97
+
109
98
  def execute
110
- self.some_value = "changed"
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("unchanged").and_return("changed") }
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
- subject(:nil_operation) do
6
- class << (operation = described_class.new(''))
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
- let(:halting_operation_instance) do
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.9.2
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: 2014-07-15 00:00:00.000000000 Z
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.0'
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.0'
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.2.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: