transproc 0.3.0 → 0.3.1
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/CHANGELOG.md +13 -1
- data/README.md +17 -10
- data/lib/transproc/coercions.rb +18 -3
- data/lib/transproc/composer.rb +0 -9
- data/lib/transproc/conditional.rb +17 -0
- data/lib/transproc/function.rb +8 -0
- data/lib/transproc/hash.rb +26 -0
- data/lib/transproc/registry.rb +21 -35
- data/lib/transproc/rspec.rb +26 -21
- data/lib/transproc/store.rb +37 -27
- data/lib/transproc/version.rb +1 -1
- data/spec/unit/coercions_spec.rb +16 -0
- data/spec/unit/conditional_spec.rb +23 -0
- data/spec/unit/function_spec.rb +41 -0
- data/spec/unit/hash_transformations_spec.rb +43 -3
- data/spec/unit/registry_spec.rb +11 -0
- data/spec/unit/store_spec.rb +15 -1
- data/spec/unit/transproc_spec.rb +2 -2
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 03da4ea0974d24e43c94ab16d920532aa9703e9d
|
4
|
+
data.tar.gz: 5d0065ee097e3574e069062388f810ed0b81b108
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dd79715c818c4161a4dbb574f8c2e359326a75739395f6ee1207dac1ffb40a138062090e2a1e94e6784ebc59dd46b8c1e036a149847ba5665ebf2635d7a53181
|
7
|
+
data.tar.gz: 915a231c2730edd26900c1ec7db8cacd5b0d7a1abc557f2e096334cf5e2092951b41b1c21239b173f257403ee42c03ffba2083dc59a31eaf5c2f9c3bddf0ee92
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,15 @@
|
|
1
|
+
## v0.3.1 2015-08-06
|
2
|
+
|
3
|
+
### Added
|
4
|
+
|
5
|
+
* `:deep_merge` in `HashTransformations` (saturnflyer)
|
6
|
+
* `Transproc::Function#to_proc` method (nepalez)
|
7
|
+
* `to_boolean` coercion turns `nil` into `false` (c0)
|
8
|
+
* Support symbolizing non-string values by `Coercions[:to_symbol]` and `HashTransformations[:symbolize_keys]` (nepalez)
|
9
|
+
* Support for importing several functions at once `import :foo, :bar, from: Foo` (nepalez)
|
10
|
+
|
11
|
+
[Compare v0.3.0...v0.3.1](https://github.com/solnic/transproc/compare/v0.3.0...v0.3.1)
|
12
|
+
|
1
13
|
## v0.3.0 2015-07-12
|
2
14
|
|
3
15
|
This release deprecates a couple of APIs and changes the way functions can be
|
@@ -26,7 +38,7 @@ in 1.0.0.
|
|
26
38
|
* `Transproc()` has been deprecated (solnic)
|
27
39
|
* `Transproc::Helper` has been deprecated (solnic)
|
28
40
|
|
29
|
-
[Compare v0.2.4...
|
41
|
+
[Compare v0.2.4...v0.3.0](https://github.com/solnic/transproc/compare/v0.2.4...v0.3.0)
|
30
42
|
|
31
43
|
## v0.2.4 2015-06-20
|
32
44
|
|
data/README.md
CHANGED
@@ -14,8 +14,9 @@
|
|
14
14
|
[][codeclimate]
|
15
15
|
[][inchpages]
|
16
16
|
|
17
|
-
|
18
|
-
|
17
|
+
Transproc is a small library that allows you to compose methods into a functional pipeline using left-to-right function composition. It works like `|>` in Elixir or `>>` in F#.
|
18
|
+
|
19
|
+
It's currently used as the data mapping backend in [Ruby Object Mapper](http://rom-rb.org).
|
19
20
|
|
20
21
|
## Installation
|
21
22
|
|
@@ -47,23 +48,27 @@ end
|
|
47
48
|
|
48
49
|
# import necessary functions from external modules
|
49
50
|
module Functions
|
50
|
-
# ...
|
51
|
-
|
52
51
|
# all transformations available in the imported module
|
53
|
-
import Transproc::
|
52
|
+
import Transproc::HashTransformations
|
54
53
|
import Transproc::ArrayTransformations
|
55
54
|
|
56
55
|
# only specific transformation (renamed into the desired local name)
|
57
56
|
import :camelize, from: Inflecto, as: :camel_case
|
58
57
|
end
|
59
58
|
|
59
|
+
def t(*args)
|
60
|
+
Functions[*args]
|
61
|
+
end
|
62
|
+
|
60
63
|
# use imported transformation
|
61
|
-
transformation =
|
64
|
+
transformation = t(:camel_case)
|
65
|
+
|
62
66
|
transformation.call 'i_am_a_camel'
|
63
67
|
# => "IAmACamel"
|
64
68
|
|
65
|
-
transformation =
|
66
|
-
transformation >>=
|
69
|
+
transformation = t(:map_array, t(:symbolize_keys) >> t(:rename_keys, user_name: :user))
|
70
|
+
transformation >>= t(:wrap, :address, [:city, :street, :zipcode])
|
71
|
+
|
67
72
|
transformation.call(
|
68
73
|
[
|
69
74
|
{ 'user_name' => 'Jane',
|
@@ -75,7 +80,8 @@ transformation.call(
|
|
75
80
|
# => [{:user=>"Jane", :address=>{:city=>"NYC", :street=>"Street 1", :zipcode=>"123"}}]
|
76
81
|
|
77
82
|
# define your own composable transformation easily
|
78
|
-
transformation =
|
83
|
+
transformation = t(-> v { JSON.dump(v) })
|
84
|
+
|
79
85
|
transformation.call(name: 'Jane')
|
80
86
|
# => "{\"name\":\"Jane\"}"
|
81
87
|
|
@@ -88,7 +94,8 @@ module Functions
|
|
88
94
|
end
|
89
95
|
end
|
90
96
|
|
91
|
-
transformation =
|
97
|
+
transformation = t(:load_json) >> t(:map_array, t(:symbolize_keys))
|
98
|
+
|
92
99
|
transformation.call('[{"name":"Jane"}]')
|
93
100
|
# => [{ :name => "Jane" }]
|
94
101
|
```
|
data/lib/transproc/coercions.rb
CHANGED
@@ -11,12 +11,27 @@ module Transproc
|
|
11
11
|
extend Registry
|
12
12
|
|
13
13
|
TRUE_VALUES = [true, 1, '1', 'on', 't', 'true', 'y', 'yes'].freeze
|
14
|
-
FALSE_VALUES = [false, 0, '0', 'off', 'f', 'false', 'n', 'no'].freeze
|
14
|
+
FALSE_VALUES = [false, 0, '0', 'off', 'f', 'false', 'n', 'no', nil].freeze
|
15
15
|
|
16
16
|
BOOLEAN_MAP = Hash[
|
17
17
|
TRUE_VALUES.product([true]) + FALSE_VALUES.product([false])
|
18
18
|
].freeze
|
19
19
|
|
20
|
+
# Does nothing and returns a value
|
21
|
+
#
|
22
|
+
# @example
|
23
|
+
# fn = Coercions[:identity]
|
24
|
+
# fn[:foo] # => :foo
|
25
|
+
#
|
26
|
+
# @param [Object] value
|
27
|
+
#
|
28
|
+
# @return [Object]
|
29
|
+
#
|
30
|
+
# @api public
|
31
|
+
def self.identity(value = nil)
|
32
|
+
value
|
33
|
+
end
|
34
|
+
|
20
35
|
# Coerce value into a string
|
21
36
|
#
|
22
37
|
# @example
|
@@ -38,13 +53,13 @@ module Transproc
|
|
38
53
|
# Transproc(:to_symbol)['foo']
|
39
54
|
# # => :foo
|
40
55
|
#
|
41
|
-
# @param [
|
56
|
+
# @param [#to_s] value The input value
|
42
57
|
#
|
43
58
|
# @return [Symbol]
|
44
59
|
#
|
45
60
|
# @api public
|
46
61
|
def self.to_symbol(value)
|
47
|
-
value.to_sym
|
62
|
+
value.to_s.to_sym
|
48
63
|
end
|
49
64
|
|
50
65
|
# Coerce value into a integer
|
data/lib/transproc/composer.rb
CHANGED
@@ -19,15 +19,6 @@ module Transproc
|
|
19
19
|
super
|
20
20
|
end
|
21
21
|
|
22
|
-
# @api private
|
23
|
-
def self.included(*)
|
24
|
-
Transproc::Deprecations.announce(
|
25
|
-
'Transproc::Helper',
|
26
|
-
'Define your own function registry using Transproc::Registry extension'
|
27
|
-
)
|
28
|
-
super
|
29
|
-
end
|
30
|
-
|
31
22
|
# @see Transproc
|
32
23
|
#
|
33
24
|
# @api public
|
@@ -15,6 +15,23 @@ module Transproc
|
|
15
15
|
module Conditional
|
16
16
|
extend Registry
|
17
17
|
|
18
|
+
# Negates the result of transformation
|
19
|
+
#
|
20
|
+
# @example
|
21
|
+
# fn = Conditional[:not, -> value { value.is_a? ::String }]
|
22
|
+
# fn[:foo] # => true
|
23
|
+
# fn["foo"] # => false
|
24
|
+
#
|
25
|
+
# @param [Object] value
|
26
|
+
# @param [Proc] fn
|
27
|
+
#
|
28
|
+
# @return [Boolean]
|
29
|
+
#
|
30
|
+
# @api public
|
31
|
+
def self.not(value, fn)
|
32
|
+
!fn[value]
|
33
|
+
end
|
34
|
+
|
18
35
|
# Apply the transformation function to subject if the predicate returns true, or return un-modified
|
19
36
|
#
|
20
37
|
# @example
|
data/lib/transproc/function.rb
CHANGED
data/lib/transproc/hash.rb
CHANGED
@@ -429,6 +429,32 @@ module Transproc
|
|
429
429
|
end
|
430
430
|
end
|
431
431
|
|
432
|
+
# Merge a hash recursively
|
433
|
+
#
|
434
|
+
# @example
|
435
|
+
#
|
436
|
+
# input = { 'foo' => 'bar', 'baz' => { 'one' => 1 } }
|
437
|
+
# other = { 'foo' => 'buz', 'baz' => { :one => 'one', :two => 2 } }
|
438
|
+
#
|
439
|
+
# t(:deep_merge)[input, other]
|
440
|
+
# # => { 'foo' => "buz", :baz => { :one => 'one', 'one' => 1, :two => 2 } }
|
441
|
+
#
|
442
|
+
# @param [Hash]
|
443
|
+
# @param [Hash]
|
444
|
+
#
|
445
|
+
# @return [Hash]
|
446
|
+
#
|
447
|
+
# @api public
|
448
|
+
def self.deep_merge(hash, other)
|
449
|
+
Hash[hash].merge(other) do |key, original_value, new_value|
|
450
|
+
if original_value.respond_to?(:to_hash) && new_value.respond_to?(:to_hash)
|
451
|
+
deep_merge(Hash[original_value], Hash[new_value])
|
452
|
+
else
|
453
|
+
new_value
|
454
|
+
end
|
455
|
+
end
|
456
|
+
end
|
457
|
+
|
432
458
|
# @deprecated Register methods globally
|
433
459
|
(methods - Registry.instance_methods - Registry.methods)
|
434
460
|
.each { |name| Transproc.register name, t(name) }
|
data/lib/transproc/registry.rb
CHANGED
@@ -54,46 +54,32 @@ module Transproc
|
|
54
54
|
#
|
55
55
|
# If the external module is a registry, looks for its imports too.
|
56
56
|
#
|
57
|
-
# @
|
58
|
-
#
|
59
|
-
#
|
60
|
-
#
|
61
|
-
#
|
62
|
-
#
|
63
|
-
#
|
64
|
-
#
|
65
|
-
#
|
66
|
-
#
|
67
|
-
#
|
68
|
-
#
|
69
|
-
#
|
70
|
-
#
|
71
|
-
#
|
72
|
-
#
|
73
|
-
#
|
74
|
-
#
|
75
|
-
#
|
76
|
-
#
|
77
|
-
# import :foo, from: Foo, as: :baz
|
78
|
-
# import :bar, from: Foo
|
79
|
-
# import Qux
|
80
|
-
# end
|
81
|
-
#
|
82
|
-
# Bar[:baz]['Qux'] # => 'QUX'
|
83
|
-
# Bar[:bar]['Qux'] # => 'qux'
|
84
|
-
# Bar[:qux]['Qux'] # => 'xuQ'
|
85
|
-
#
|
86
|
-
# @param [Module, #to_sym] name
|
87
|
-
# @option [Module] :from The module to take the method from
|
88
|
-
# @option [#to_sym] :as
|
89
|
-
# The name of imported transproc inside the current module
|
57
|
+
# @overload import(source)
|
58
|
+
# Loads all methods from the source object
|
59
|
+
#
|
60
|
+
# @param [Object] source
|
61
|
+
#
|
62
|
+
# @overload import(*names, **options)
|
63
|
+
# Loads selected methods from the source object
|
64
|
+
#
|
65
|
+
# @param [Array<Symbol>] names
|
66
|
+
# @param [Hash] options
|
67
|
+
# @options options [Object] :from The source object
|
68
|
+
#
|
69
|
+
# @overload import(name, **options)
|
70
|
+
# Loads selected methods from the source object
|
71
|
+
#
|
72
|
+
# @param [Symbol] name
|
73
|
+
# @param [Hash] options
|
74
|
+
# @options options [Object] :from The source object
|
75
|
+
# @options options [Object] :as The new name for the transformation
|
90
76
|
#
|
91
77
|
# @return [itself] self
|
92
78
|
#
|
93
79
|
# @alias :import
|
94
80
|
#
|
95
|
-
def import(
|
96
|
-
@store = store.import(
|
81
|
+
def import(*args)
|
82
|
+
@store = store.import(*args)
|
97
83
|
self
|
98
84
|
end
|
99
85
|
alias_method :uses, :import
|
data/lib/transproc/rspec.rb
CHANGED
@@ -5,21 +5,23 @@
|
|
5
5
|
# ==============================================================================
|
6
6
|
|
7
7
|
shared_context :call_transproc do
|
8
|
-
let!(:
|
9
|
-
let!(:
|
10
|
-
|
8
|
+
let!(:__initial__) { input.dup rescue input }
|
9
|
+
let!(:__fn__) { described_class[*arguments] }
|
10
|
+
subject { __fn__[input] }
|
11
11
|
end
|
12
12
|
|
13
13
|
shared_examples :transforming_data do
|
14
|
+
include_context :call_transproc
|
15
|
+
|
14
16
|
it '[returns the expected output]' do
|
15
|
-
expect(
|
17
|
+
expect(subject).to eql(output), <<-REPORT.gsub(/.+\|/, "")
|
16
18
|
|
|
17
19
|
|fn = #{described_class}#{Array[*arguments]}
|
18
20
|
|
|
19
21
|
|fn[#{input}]
|
20
22
|
|
|
21
23
|
| expected: #{output}
|
22
|
-
| got: #{
|
24
|
+
| got: #{subject}
|
23
25
|
REPORT
|
24
26
|
end
|
25
27
|
end
|
@@ -30,13 +32,14 @@ shared_examples :transforming_immutable_data do
|
|
30
32
|
it_behaves_like :transforming_data
|
31
33
|
|
32
34
|
it '[keeps input unchanged]' do
|
33
|
-
expect
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
35
|
+
expect { subject }
|
36
|
+
.not_to change { input }, <<-REPORT.gsub(/.+\|/, "")
|
37
|
+
|
|
38
|
+
|fn = #{described_class}#{Array[*arguments]}
|
39
|
+
|
|
40
|
+
|expected: not to change #{__initial__}
|
41
|
+
| got: changed it to #{input}
|
42
|
+
REPORT
|
40
43
|
end
|
41
44
|
end
|
42
45
|
|
@@ -46,14 +49,16 @@ shared_examples :mutating_input_data do
|
|
46
49
|
it_behaves_like :transforming_data
|
47
50
|
|
48
51
|
it '[changes input]' do
|
49
|
-
expect
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
52
|
+
expect { subject }
|
53
|
+
.to change { input }
|
54
|
+
.to(output), <<-REPORT.gsub(/.+\|/, "")
|
55
|
+
|
|
56
|
+
|fn = #{described_class}#{Array[*arguments]}
|
57
|
+
|
|
58
|
+
|fn[#{input}]
|
59
|
+
|
|
60
|
+
|expected: to change input to #{output}
|
61
|
+
| got: #{input}
|
62
|
+
REPORT
|
58
63
|
end
|
59
64
|
end
|
data/lib/transproc/store.rb
CHANGED
@@ -38,17 +38,18 @@ module Transproc
|
|
38
38
|
|
39
39
|
# Imports proc(s) to the collection from another module
|
40
40
|
#
|
41
|
-
# @
|
42
|
-
# @param (see #import_methods)
|
43
|
-
# @return (see #import_methods)
|
44
|
-
#
|
45
|
-
# @overload add(source, options)
|
46
|
-
# @param (see #import_method)
|
47
|
-
# @return (see #import_method)
|
41
|
+
# @private
|
48
42
|
#
|
49
|
-
def import(
|
50
|
-
|
51
|
-
|
43
|
+
def import(*args)
|
44
|
+
first = args.first
|
45
|
+
return import_all(first) if first.instance_of?(Module)
|
46
|
+
|
47
|
+
opts = args.pop
|
48
|
+
source = opts.fetch(:from)
|
49
|
+
rename = opts.fetch(:as) { first.to_sym }
|
50
|
+
|
51
|
+
return import_methods(source, args) if args.count > 1
|
52
|
+
import_method(source, first, rename)
|
52
53
|
end
|
53
54
|
|
54
55
|
protected
|
@@ -57,22 +58,31 @@ module Transproc
|
|
57
58
|
# updated with either the module's singleton method,
|
58
59
|
# or the proc having been imported from another module.
|
59
60
|
#
|
60
|
-
# @param [
|
61
|
-
# @param [
|
62
|
-
# @
|
63
|
-
# The module whose method or imported proc should be added
|
64
|
-
# @option options [Symbol] :as
|
65
|
-
# The key for the proc in the current collection
|
61
|
+
# @param [Module] source
|
62
|
+
# @param [Symbol] name
|
63
|
+
# @param [Symbol] new_name
|
66
64
|
#
|
67
65
|
# @return [Transproc::Store]
|
68
66
|
#
|
69
|
-
def import_method(source,
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
fn
|
67
|
+
def import_method(source, name, new_name = name)
|
68
|
+
from = name.to_sym
|
69
|
+
to = new_name.to_sym
|
70
|
+
|
71
|
+
fn = source.is_a?(Registry) ? source.fetch(from) : source.method(from)
|
72
|
+
self.class.new(methods.merge(to => fn))
|
73
|
+
end
|
74
74
|
|
75
|
-
|
75
|
+
# Creates new immutable collection from the current one,
|
76
|
+
# updated with either the module's singleton methods,
|
77
|
+
# or the procs having been imported from another module.
|
78
|
+
#
|
79
|
+
# @param [Module] source
|
80
|
+
# @param [Array<Symbol>] names
|
81
|
+
#
|
82
|
+
# @return [Transproc::Store]
|
83
|
+
#
|
84
|
+
def import_methods(source, names)
|
85
|
+
names.inject(self) { |a, e| a.import_method(source, e) }
|
76
86
|
end
|
77
87
|
|
78
88
|
# Creates new immutable collection from the current one,
|
@@ -83,12 +93,12 @@ module Transproc
|
|
83
93
|
#
|
84
94
|
# @return [Transproc::Store]
|
85
95
|
#
|
86
|
-
def
|
87
|
-
|
88
|
-
|
89
|
-
|
96
|
+
def import_all(source)
|
97
|
+
names = source.public_methods - Registry.instance_methods - Module.methods
|
98
|
+
names -= [:initialize] # for compatibility with Rubinius
|
99
|
+
names += source.store.methods.keys if source.is_a? Registry
|
90
100
|
|
91
|
-
|
101
|
+
import_methods(source, names)
|
92
102
|
end
|
93
103
|
end # class Store
|
94
104
|
end # module Transproc
|
data/lib/transproc/version.rb
CHANGED
data/spec/unit/coercions_spec.rb
CHANGED
@@ -1,6 +1,18 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Transproc::Coercions do
|
4
|
+
describe '.identity' do
|
5
|
+
let(:fn) { described_class.t(:identity) }
|
6
|
+
|
7
|
+
it 'returns the original value' do
|
8
|
+
expect(fn[:foo]).to eql :foo
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'returns nil by default' do
|
12
|
+
expect(fn[]).to eql nil
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
4
16
|
describe '.to_string' do
|
5
17
|
it 'turns integer into a string' do
|
6
18
|
expect(described_class.t(:to_string)[1]).to eql('1')
|
@@ -11,6 +23,10 @@ describe Transproc::Coercions do
|
|
11
23
|
it 'turns string into a symbol' do
|
12
24
|
expect(described_class.t(:to_symbol)['test']).to eql(:test)
|
13
25
|
end
|
26
|
+
|
27
|
+
it 'turns non-string into a symbol' do
|
28
|
+
expect(described_class.t(:to_symbol)[1]).to eql(:'1')
|
29
|
+
end
|
14
30
|
end
|
15
31
|
|
16
32
|
describe '.to_integer' do
|
@@ -1,6 +1,29 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Transproc::Conditional do
|
4
|
+
describe '.not' do
|
5
|
+
let(:fn) { described_class.t(:not, -> value { value.is_a? String }) }
|
6
|
+
subject { fn[input] }
|
7
|
+
|
8
|
+
context 'when predicate returns truthy value' do
|
9
|
+
let(:input) { 'foo' }
|
10
|
+
let(:output) { false }
|
11
|
+
|
12
|
+
it 'applies the first transformation' do
|
13
|
+
expect(subject).to eql output
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
context 'when predicate returns falsey value' do
|
18
|
+
let(:input) { :foo }
|
19
|
+
let(:output) { true }
|
20
|
+
|
21
|
+
it 'applies the first transformation' do
|
22
|
+
expect(subject).to eql output
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
4
27
|
describe '.guard' do
|
5
28
|
let(:fn) { described_class.t(:guard, condition, operation) }
|
6
29
|
let(:condition) { ->(value) { value.is_a?(::String) } }
|
data/spec/unit/function_spec.rb
CHANGED
@@ -117,4 +117,45 @@ describe Transproc::Function do
|
|
117
117
|
expect(left == right).to be(false)
|
118
118
|
end
|
119
119
|
end
|
120
|
+
|
121
|
+
describe '#to_proc' do
|
122
|
+
shared_examples :providing_a_proc do
|
123
|
+
let(:fn) { described_class.new(source) }
|
124
|
+
subject { fn.to_proc }
|
125
|
+
|
126
|
+
it 'returns a proc' do
|
127
|
+
expect(subject).to be_instance_of Proc
|
128
|
+
end
|
129
|
+
|
130
|
+
it 'works fine' do
|
131
|
+
expect(subject.call :foo).to eql('foo')
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
context 'from a method' do
|
136
|
+
let(:source) do
|
137
|
+
mod = Module.new do
|
138
|
+
def self.get(x)
|
139
|
+
x.to_s
|
140
|
+
end
|
141
|
+
end
|
142
|
+
mod.method(:get)
|
143
|
+
end
|
144
|
+
it_behaves_like :providing_a_proc
|
145
|
+
end
|
146
|
+
|
147
|
+
context 'from a proc' do
|
148
|
+
let(:source) { -> value { value.to_s } }
|
149
|
+
it_behaves_like :providing_a_proc
|
150
|
+
end
|
151
|
+
|
152
|
+
context 'from a transproc' do
|
153
|
+
let(:source) { Transproc::Function.new -> value { value.to_s } }
|
154
|
+
it_behaves_like :providing_a_proc
|
155
|
+
|
156
|
+
it 'can be applied to collection' do
|
157
|
+
expect([:foo, :bar].map(&source)).to eql(%w(foo bar))
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
120
161
|
end
|
@@ -30,11 +30,11 @@ describe Transproc::HashTransformations do
|
|
30
30
|
it 'returns a new hash with symbolized keys' do
|
31
31
|
symbolize_keys = described_class.t(:symbolize_keys)
|
32
32
|
|
33
|
-
input = {
|
34
|
-
output = {
|
33
|
+
input = { 1 => 'bar' }
|
34
|
+
output = { :'1' => 'bar' }
|
35
35
|
|
36
36
|
expect(symbolize_keys[input]).to eql(output)
|
37
|
-
expect
|
37
|
+
expect { symbolize_keys[input] }.not_to change { input }
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
@@ -509,4 +509,44 @@ describe Transproc::HashTransformations do
|
|
509
509
|
expect(result[:hash]).to eql(one: 1)
|
510
510
|
end
|
511
511
|
end
|
512
|
+
|
513
|
+
describe '.deep_merge' do
|
514
|
+
let(:hash){
|
515
|
+
{
|
516
|
+
name: 'Jane',
|
517
|
+
email: 'jane@doe.org',
|
518
|
+
favorites:
|
519
|
+
{
|
520
|
+
food: 'stroopwafel'
|
521
|
+
}
|
522
|
+
}
|
523
|
+
}
|
524
|
+
|
525
|
+
let(:update){
|
526
|
+
{
|
527
|
+
email: 'jane@example.org',
|
528
|
+
favorites:
|
529
|
+
{
|
530
|
+
color: 'orange'
|
531
|
+
}
|
532
|
+
}
|
533
|
+
}
|
534
|
+
|
535
|
+
it 'recursively merges hash values' do
|
536
|
+
deep_merge = described_class.t(:deep_merge)
|
537
|
+
output = { name: 'Jane', email: 'jane@example.org', favorites: { food: 'stroopwafel', color: 'orange' } }
|
538
|
+
|
539
|
+
expect(deep_merge[hash, update]).to eql(output)
|
540
|
+
end
|
541
|
+
|
542
|
+
it 'does not alter the provided arguments' do
|
543
|
+
original_hash = hash.dup
|
544
|
+
original_update = update.dup
|
545
|
+
|
546
|
+
described_class.t(:deep_merge)[hash, update]
|
547
|
+
|
548
|
+
expect(hash).to eql(original_hash)
|
549
|
+
expect(update).to eql(original_update)
|
550
|
+
end
|
551
|
+
end
|
512
552
|
end
|
data/spec/unit/registry_spec.rb
CHANGED
@@ -77,6 +77,17 @@ describe Transproc::Registry do
|
|
77
77
|
end
|
78
78
|
end
|
79
79
|
|
80
|
+
context 'a list of methods' do
|
81
|
+
before { bar.import :prefix, from: foo }
|
82
|
+
before { bar.import :prefix, from: foo, as: :affix }
|
83
|
+
before { baz.import :prefix, :affix, from: bar }
|
84
|
+
|
85
|
+
it 'registers a transproc' do
|
86
|
+
expect(baz[:prefix, 'bar']['baz']).to eql 'bar_baz'
|
87
|
+
expect(baz[:affix, 'bar']['baz']).to eql 'bar_baz'
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
80
91
|
context 'a renamed method' do
|
81
92
|
before { bar.import :prefix, from: foo, as: :affix }
|
82
93
|
|
data/spec/unit/store_spec.rb
CHANGED
@@ -38,7 +38,7 @@ describe Transproc::Store do
|
|
38
38
|
end
|
39
39
|
end # describe #fetch
|
40
40
|
|
41
|
-
describe '#import' do
|
41
|
+
describe '#import', :focus do
|
42
42
|
before do
|
43
43
|
module Bar
|
44
44
|
def self.bar
|
@@ -91,6 +91,20 @@ describe Transproc::Store do
|
|
91
91
|
end
|
92
92
|
end
|
93
93
|
|
94
|
+
context 'named methods' do
|
95
|
+
subject { store.import 'qux', 'bar', from: Qux }
|
96
|
+
|
97
|
+
it_behaves_like :importing_method do
|
98
|
+
let(:key) { :qux }
|
99
|
+
let(:value) { :qux }
|
100
|
+
end
|
101
|
+
|
102
|
+
it_behaves_like :importing_method do
|
103
|
+
let(:key) { :bar }
|
104
|
+
let(:value) { :bar }
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
94
108
|
context 'renamed method' do
|
95
109
|
subject { store.import 'qux', from: Qux, as: 'quxx' }
|
96
110
|
|
data/spec/unit/transproc_spec.rb
CHANGED
@@ -17,11 +17,11 @@ describe Transproc do
|
|
17
17
|
|
18
18
|
describe '.register' do
|
19
19
|
it 'allows registering functions by name' do
|
20
|
-
Transproc.register(:
|
20
|
+
Transproc.register(:id, -> value { value })
|
21
21
|
|
22
22
|
value = 'hello world'
|
23
23
|
|
24
|
-
result = t(:
|
24
|
+
result = t(:id)[value]
|
25
25
|
|
26
26
|
expect(result).to be(value)
|
27
27
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: transproc
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Piotr Solnica
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-08-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|