transproc 1.0.3 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +15 -0
  3. data/.gitignore +3 -0
  4. data/.travis.yml +10 -10
  5. data/CHANGELOG.md +14 -2
  6. data/Gemfile +5 -17
  7. data/lib/transproc.rb +3 -4
  8. data/lib/transproc/all.rb +2 -0
  9. data/lib/transproc/array.rb +2 -0
  10. data/lib/transproc/array/combine.rb +2 -0
  11. data/lib/transproc/class.rb +2 -0
  12. data/lib/transproc/coercions.rb +2 -0
  13. data/lib/transproc/compiler.rb +45 -0
  14. data/lib/transproc/composer.rb +2 -0
  15. data/lib/transproc/composite.rb +2 -0
  16. data/lib/transproc/conditional.rb +2 -0
  17. data/lib/transproc/constants.rb +5 -0
  18. data/lib/transproc/error.rb +2 -0
  19. data/lib/transproc/function.rb +2 -0
  20. data/lib/transproc/functions.rb +2 -0
  21. data/lib/transproc/hash.rb +31 -0
  22. data/lib/transproc/proc.rb +2 -0
  23. data/lib/transproc/recursion.rb +2 -0
  24. data/lib/transproc/registry.rb +1 -0
  25. data/lib/transproc/store.rb +1 -0
  26. data/lib/transproc/support/deprecations.rb +2 -0
  27. data/lib/transproc/transformer.rb +7 -1
  28. data/lib/transproc/transformer/class_interface.rb +31 -65
  29. data/lib/transproc/transformer/deprecated/class_interface.rb +80 -0
  30. data/lib/transproc/transformer/dsl.rb +51 -0
  31. data/lib/transproc/version.rb +3 -1
  32. data/spec/spec_helper.rb +5 -7
  33. data/spec/unit/array/combine_spec.rb +3 -1
  34. data/spec/unit/array_transformations_spec.rb +1 -1
  35. data/spec/unit/class_transformations_spec.rb +9 -6
  36. data/spec/unit/coercions_spec.rb +1 -1
  37. data/spec/unit/composer_spec.rb +1 -1
  38. data/spec/unit/conditional_spec.rb +1 -1
  39. data/spec/unit/function_not_found_error_spec.rb +1 -1
  40. data/spec/unit/function_spec.rb +1 -1
  41. data/spec/unit/hash_transformations_spec.rb +12 -1
  42. data/spec/unit/proc_transformations_spec.rb +3 -1
  43. data/spec/unit/recursion_spec.rb +1 -1
  44. data/spec/unit/registry_spec.rb +1 -1
  45. data/spec/unit/store_spec.rb +2 -1
  46. data/spec/unit/transformer/class_interface_spec.rb +364 -0
  47. data/spec/unit/transformer/dsl_spec.rb +15 -0
  48. data/spec/unit/transformer/instance_methods_spec.rb +25 -0
  49. data/spec/unit/transformer_spec.rb +128 -40
  50. data/spec/unit/transproc_spec.rb +1 -1
  51. data/transproc.gemspec +0 -4
  52. metadata +15 -53
  53. data/.rubocop.yml +0 -66
  54. data/.rubocop_todo.yml +0 -11
  55. data/rakelib/mutant.rake +0 -16
  56. data/rakelib/rubocop.rake +0 -18
  57. data/spec/support/mutant.rb +0 -10
@@ -0,0 +1,15 @@
1
+ RSpec.describe Transproc::Transformer do
2
+ let(:container) { Module.new { extend Transproc::Registry } }
3
+ let(:klass) { Transproc::Transformer[container] }
4
+ let(:transformer) { klass.new }
5
+
6
+ context 'when invalid method is used' do
7
+ it 'raises an error on initialization' do
8
+ klass.define! do
9
+ not_valid
10
+ end
11
+
12
+ expect { klass.new }.to raise_error(Transproc::Compiler::InvalidFunctionNameError, /not_valid/)
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,25 @@
1
+ RSpec.describe Transproc::Transformer, 'instance methods' do
2
+ subject(:transformer) do
3
+ Class.new(Transproc::Transformer[registry]) do
4
+ define! do
5
+ map_array(&:capitalize)
6
+ end
7
+
8
+ def capitalize(input)
9
+ input.upcase
10
+ end
11
+ end.new
12
+ end
13
+
14
+ let(:registry) do
15
+ Module.new do
16
+ extend Transproc::Registry
17
+
18
+ import Transproc::ArrayTransformations
19
+ end
20
+ end
21
+
22
+ it 'registers a new transformation function' do
23
+ expect(transformer.call(%w[foo bar])).to eql(%w[FOO BAR])
24
+ end
25
+ end
@@ -1,4 +1,7 @@
1
- require 'spec_helper'
1
+ # frozen_string_literal: true
2
+
3
+ require 'ostruct'
4
+ require 'dry/equalizer'
2
5
 
3
6
  describe Transproc::Transformer do
4
7
  let(:container) { Module.new { extend Transproc::Registry } }
@@ -6,23 +9,76 @@ describe Transproc::Transformer do
6
9
  let(:transformer) { klass.new }
7
10
 
8
11
  describe '.container' do
9
- it { expect(klass.container).to eq container }
12
+ it 'returns the configured container' do
13
+ expect(klass.container).to be(container)
14
+ end
10
15
 
11
- context 'with default transformer' do
12
- let(:klass) { described_class }
16
+ context 'with setter argument' do
17
+ let(:container) { double(:custom_container) }
18
+
19
+ it 'sets and returns the container' do
20
+ klass.container(container)
13
21
 
14
- it 'raises exception because there is no container by default' do
15
- message = 'Transformer function registry is empty. '\
16
- 'Provide your registry via Transproc::Transformer[YourRegistry]'
17
- expect { klass.container }.to raise_error(ArgumentError, message)
22
+ expect(klass.container).to be(container)
18
23
  end
19
24
  end
25
+ end
20
26
 
21
- context 'with setter argument' do
22
- subject! { klass.container({}) }
27
+ describe '.method_missing' do
28
+ context 'when the method name matches a registered function' do
29
+ it 'registers a transformation without args' do
30
+ container.import(Transproc::Coercions)
23
31
 
24
- it 'sets and returns the container' do
25
- expect(klass.container).to eq({})
32
+ func = klass.t(:to_string)
33
+
34
+ result = klass.to_string
35
+
36
+ expect(result).to eql(func)
37
+ end
38
+
39
+ it 'registers a transformation with args' do
40
+ container.import(Transproc::HashTransformations)
41
+
42
+ func = klass.t(:rename_keys, id: :user_id)
43
+
44
+ result = klass.rename_keys(id: :user_id)
45
+
46
+ expect(result).to eql(func)
47
+ end
48
+
49
+ it 'registers a transformation with a block' do
50
+ container.import(Transproc::ArrayTransformations)
51
+ container.import(Transproc::HashTransformations)
52
+
53
+ func = klass.t(:map_array, klass.t(:rename_keys, id: :user_id))
54
+
55
+ result = klass.map_array { rename_keys(id: :user_id) }
56
+
57
+ expect(result).to eql(func)
58
+ end
59
+
60
+ it 'registers a transformation with args and a block' do
61
+ container.import(Transproc::HashTransformations)
62
+
63
+ func = klass.t(:map_value, :user, klass.t(:rename_keys, id: :user_id))
64
+
65
+ result = klass.map_value(:user) { rename_keys(id: :user_id) }
66
+
67
+ expect(result).to eql(func)
68
+ end
69
+
70
+ it 'works with #method' do
71
+ container.import(Transproc::Coercions)
72
+
73
+ func = klass.t(:to_string)
74
+
75
+ expect(klass.method(:to_string).()).to eql(func)
76
+ end
77
+ end
78
+
79
+ context 'when the method name does not match any registered function' do
80
+ it 'raises NoMethodError' do
81
+ expect { klass.not_here }.to raise_error(NoMethodError, /not_here/)
26
82
  end
27
83
  end
28
84
  end
@@ -37,11 +93,13 @@ describe Transproc::Transformer do
37
93
  end
38
94
  end
39
95
  end
96
+
40
97
  let(:superclass) do
41
98
  Class.new(Transproc::Transformer[container]) do
42
99
  arbitrary ->(v) { v + 1 }
43
100
  end
44
101
  end
102
+
45
103
  let(:subclass) do
46
104
  Class.new(superclass) do
47
105
  arbitrary ->(v) { v * 2 }
@@ -49,38 +107,53 @@ describe Transproc::Transformer do
49
107
  end
50
108
 
51
109
  it 'inherits container from superclass' do
52
- expect(subclass.container).to eq superclass.container
110
+ expect(subclass.container).to be(superclass.container)
53
111
  end
54
112
 
55
- it 'does not inherit transproc from superclass' do
56
- expect(superclass.new.call(2)).to eq 3
57
- expect(subclass.new.call(2)).to eq 4
113
+ it 'inherits transproc from superclass' do
114
+ expect(superclass.new.call(2)).to be(3)
115
+ expect(subclass.new.call(2)).to be(6)
58
116
  end
59
117
  end
60
118
 
61
119
  describe '.[]' do
120
+ subject(:subclass) { klass[another_container] }
121
+
62
122
  let(:another_container) { double('Transproc') }
63
123
 
64
- subject(:subclass) { klass[another_container] }
124
+ it 'sets a container' do
125
+ expect(subclass.container).to be(another_container)
126
+ end
65
127
 
66
- it { expect(subclass.container).to eq(another_container) }
67
- it { is_expected.to be_a(::Class) }
68
- it { expect(subclass.ancestors).to include(Transproc::Transformer) }
128
+ it 'returns a class' do
129
+ expect(subclass).to be_a(Class)
130
+ end
131
+
132
+ it 'creates a subclass of Transformer' do
133
+ expect(subclass).to be < Transproc::Transformer
134
+ end
69
135
 
70
136
  it 'does not change super class' do
71
- expect(klass.container).to eq(container)
137
+ expect(klass.container).to be(container)
138
+ end
139
+
140
+ it 'does not inherit transproc' do
141
+ expect(klass[container].transproc).to be_nil
72
142
  end
73
143
 
74
144
  context 'with predefined transformer' do
75
145
  let(:klass) do
76
- Class.new(Transproc::Transformer) do
146
+ Class.new(Transproc::Transformer[container]) do
147
+ container.import Transproc::Coercions
148
+ container.import Transproc::HashTransformations
149
+
77
150
  map_value :attr, t(:to_symbol)
78
151
  end
79
152
  end
80
- end
81
153
 
82
- it 'does not inherit transproc' do
83
- expect(klass[container].transproc).to be_nil
154
+ it "inherits parent's transproc" do
155
+ expect(klass[container].transproc).to eql(klass.transproc)
156
+ end
84
157
  end
85
158
  end
86
159
 
@@ -96,12 +169,14 @@ describe Transproc::Transformer do
96
169
  end
97
170
  end
98
171
  end
172
+
99
173
  let(:klass) { Transproc::Transformer[container] }
100
174
 
101
175
  it 'defines anonymous transproc' do
102
176
  transproc = klass.define do
103
177
  map_value(:attr, t(:to_symbol))
104
178
  end
179
+
105
180
  expect(transproc[attr: 'abc']).to eq(attr: :abc)
106
181
  end
107
182
 
@@ -109,6 +184,7 @@ describe Transproc::Transformer do
109
184
  transproc = klass.build do
110
185
  map_value(:attr, t(:to_symbol))
111
186
  end
187
+
112
188
  expect(transproc[attr: 'abc']).to eq(attr: :abc)
113
189
  end
114
190
 
@@ -116,6 +192,7 @@ describe Transproc::Transformer do
116
192
  klass.define do
117
193
  map_value(:attr, :to_sym.to_proc)
118
194
  end
195
+
119
196
  expect(klass.transproc).to be_nil
120
197
  end
121
198
 
@@ -129,12 +206,14 @@ describe Transproc::Transformer do
129
206
  end
130
207
  end
131
208
  end
209
+
132
210
  let(:klass) { described_class[container] }
133
211
 
134
212
  it 'uses a container from the transformer' do
135
213
  transproc = klass.define do
136
214
  arbitrary ->(v) { v + 1 }
137
215
  end
216
+
138
217
  expect(transproc.call(2)).to eq 3
139
218
  end
140
219
  end
@@ -155,12 +234,15 @@ describe Transproc::Transformer do
155
234
  transproc = klass.define do
156
235
  map_value :attr, ->(v) { v * 2 }
157
236
  end
237
+
158
238
  expect(transproc.call(attr: 2)).to eq(attr: 4)
159
239
  end
160
240
  end
161
241
  end
162
242
 
163
243
  describe '.t' do
244
+ subject(:klass) { Transproc::Transformer[container] }
245
+
164
246
  let(:container) do
165
247
  Module.new do
166
248
  extend Transproc::Registry
@@ -174,9 +256,9 @@ describe Transproc::Transformer do
174
256
  end
175
257
  end
176
258
 
177
- subject!(:klass) { Transproc::Transformer[container] }
178
-
179
- it { expect(klass.t(:custom, '_bar')).to eq container[:custom, '_bar'] }
259
+ it 'returns a registed function' do
260
+ expect(klass.t(:custom, '_bar')).to eql(container[:custom, '_bar'])
261
+ end
180
262
 
181
263
  it 'is useful in DSL' do
182
264
  transproc = Class.new(klass) do
@@ -214,13 +296,16 @@ describe Transproc::Transformer do
214
296
  symbolize_keys
215
297
  rename_keys user_name: :name
216
298
  nest :address, [:city, :street, :zipcode]
299
+
217
300
  map_value :address do
218
301
  constructor_inject Test::Address
219
302
  end
303
+
220
304
  constructor_inject Test::User
221
305
  end
222
306
  end
223
307
  end
308
+
224
309
  let(:input) do
225
310
  [
226
311
  { 'user_name' => 'Jane',
@@ -230,7 +315,8 @@ describe Transproc::Transformer do
230
315
  }
231
316
  ]
232
317
  end
233
- let(:output) do
318
+
319
+ let(:expected_output) do
234
320
  [
235
321
  Test::User.new(
236
322
  name: 'Jane',
@@ -245,38 +331,40 @@ describe Transproc::Transformer do
245
331
 
246
332
  before do
247
333
  module Test
248
- class User
249
- include Anima.new(:name, :address)
334
+ class User < OpenStruct
335
+ include Dry::Equalizer(:name, :address)
250
336
  end
251
337
 
252
- class Address
253
- include Anima.new(:city, :street, :zipcode)
338
+ class Address < OpenStruct
339
+ include Dry::Equalizer(:city, :street, :zipcode)
254
340
  end
255
341
  end
256
342
  end
257
343
 
258
- subject! { transformer.call(input) }
259
-
260
- it { is_expected.to eq(output) }
344
+ it "transforms input" do
345
+ expect(transformer.(input)).to eql(expected_output)
346
+ end
261
347
 
262
348
  context 'with custom registry' do
263
349
  let(:klass) do
264
350
  Class.new(Transproc::Transformer[registry]) do
265
- custom ' is awesome'
351
+ append ' is awesome'
266
352
  end
267
353
  end
354
+
268
355
  let(:registry) do
269
356
  Module.new do
270
357
  extend Transproc::Registry
271
358
 
272
- def self.custom(value, suffix)
359
+ def self.append(value, suffix)
273
360
  value + suffix
274
361
  end
275
362
  end
276
363
  end
277
- let(:input) { 'transproc' }
278
364
 
279
- it { is_expected.to eq('transproc is awesome') }
365
+ it 'uses custom functions' do
366
+ expect(transformer.('transproc')).to eql('transproc is awesome')
367
+ end
280
368
  end
281
369
  end
282
370
  end
@@ -1,4 +1,4 @@
1
- require 'spec_helper'
1
+ # frozen_string_literal: true
2
2
 
3
3
  describe Transproc do
4
4
  describe 'composition' do
@@ -17,8 +17,4 @@ Gem::Specification.new do |spec|
17
17
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
18
  spec.require_paths = ['lib']
19
19
  spec.required_ruby_version = '>= 2.3.0'
20
-
21
- spec.add_development_dependency 'bundler', '~> 1.7'
22
- spec.add_development_dependency 'rake', '~> 10.0'
23
- spec.add_development_dependency 'rspec', '~> 3.3'
24
20
  end
metadata CHANGED
@@ -1,57 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: transproc
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.3
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Piotr Solnica
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-12-01 00:00:00.000000000 Z
12
- dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: bundler
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - "~>"
18
- - !ruby/object:Gem::Version
19
- version: '1.7'
20
- type: :development
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - "~>"
25
- - !ruby/object:Gem::Version
26
- version: '1.7'
27
- - !ruby/object:Gem::Dependency
28
- name: rake
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - "~>"
32
- - !ruby/object:Gem::Version
33
- version: '10.0'
34
- type: :development
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - "~>"
39
- - !ruby/object:Gem::Version
40
- version: '10.0'
41
- - !ruby/object:Gem::Dependency
42
- name: rspec
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - "~>"
46
- - !ruby/object:Gem::Version
47
- version: '3.3'
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - "~>"
53
- - !ruby/object:Gem::Version
54
- version: '3.3'
11
+ date: 2019-07-18 00:00:00.000000000 Z
12
+ dependencies: []
55
13
  description: Transform Ruby objects in functional style
56
14
  email:
57
15
  - piotr.solnica@gmail.com
@@ -59,10 +17,9 @@ executables: []
59
17
  extensions: []
60
18
  extra_rdoc_files: []
61
19
  files:
20
+ - ".codeclimate.yml"
62
21
  - ".gitignore"
63
22
  - ".rspec"
64
- - ".rubocop.yml"
65
- - ".rubocop_todo.yml"
66
23
  - ".travis.yml"
67
24
  - CHANGELOG.md
68
25
  - Gemfile
@@ -76,9 +33,11 @@ files:
76
33
  - lib/transproc/array/combine.rb
77
34
  - lib/transproc/class.rb
78
35
  - lib/transproc/coercions.rb
36
+ - lib/transproc/compiler.rb
79
37
  - lib/transproc/composer.rb
80
38
  - lib/transproc/composite.rb
81
39
  - lib/transproc/conditional.rb
40
+ - lib/transproc/constants.rb
82
41
  - lib/transproc/error.rb
83
42
  - lib/transproc/function.rb
84
43
  - lib/transproc/functions.rb
@@ -90,11 +49,10 @@ files:
90
49
  - lib/transproc/support/deprecations.rb
91
50
  - lib/transproc/transformer.rb
92
51
  - lib/transproc/transformer/class_interface.rb
52
+ - lib/transproc/transformer/deprecated/class_interface.rb
53
+ - lib/transproc/transformer/dsl.rb
93
54
  - lib/transproc/version.rb
94
- - rakelib/mutant.rake
95
- - rakelib/rubocop.rake
96
55
  - spec/spec_helper.rb
97
- - spec/support/mutant.rb
98
56
  - spec/unit/array/combine_spec.rb
99
57
  - spec/unit/array_transformations_spec.rb
100
58
  - spec/unit/class_transformations_spec.rb
@@ -108,6 +66,9 @@ files:
108
66
  - spec/unit/recursion_spec.rb
109
67
  - spec/unit/registry_spec.rb
110
68
  - spec/unit/store_spec.rb
69
+ - spec/unit/transformer/class_interface_spec.rb
70
+ - spec/unit/transformer/dsl_spec.rb
71
+ - spec/unit/transformer/instance_methods_spec.rb
111
72
  - spec/unit/transformer_spec.rb
112
73
  - spec/unit/transproc_spec.rb
113
74
  - transproc.gemspec
@@ -130,14 +91,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
130
91
  - !ruby/object:Gem::Version
131
92
  version: '0'
132
93
  requirements: []
133
- rubyforge_project:
134
- rubygems_version: 2.7.6
94
+ rubygems_version: 3.0.3
135
95
  signing_key:
136
96
  specification_version: 4
137
97
  summary: Transform Ruby objects in functional style
138
98
  test_files:
139
99
  - spec/spec_helper.rb
140
- - spec/support/mutant.rb
141
100
  - spec/unit/array/combine_spec.rb
142
101
  - spec/unit/array_transformations_spec.rb
143
102
  - spec/unit/class_transformations_spec.rb
@@ -151,5 +110,8 @@ test_files:
151
110
  - spec/unit/recursion_spec.rb
152
111
  - spec/unit/registry_spec.rb
153
112
  - spec/unit/store_spec.rb
113
+ - spec/unit/transformer/class_interface_spec.rb
114
+ - spec/unit/transformer/dsl_spec.rb
115
+ - spec/unit/transformer/instance_methods_spec.rb
154
116
  - spec/unit/transformer_spec.rb
155
117
  - spec/unit/transproc_spec.rb