transproc 0.1.3 → 0.2.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: b43b407d9915f16f63dbf1a12f10c9a87228213c
4
- data.tar.gz: a46a7614a839a50da267593eeef25acbc8db167b
3
+ metadata.gz: 2cc7103ff3c33f4d49ebf8bd85f049500f5b0a27
4
+ data.tar.gz: 08c4676baf065be02235c2a9885d62fadb514311
5
5
  SHA512:
6
- metadata.gz: 5ce15554b0639b3c79a0a4da686e588f01dd0de7798b89a7129c39b0a51f0f0c31b094533775b3b21f5b6b893917020f2d99aa1b84648c445617c75f3f8e5688
7
- data.tar.gz: 104618d775a9ce9781583b2c6f4e0e61ca28107f1f4494124b41456c8442b4663a7d4ad5b353dd6641b0e885f56d5b33ee0d0a32e23ff5a6ad4c9fcf2f029e96
6
+ metadata.gz: a532a67708497aa9ddc6e53c10bddbcc1b0c9c71ac648b05f59b9d4c24ec61e08d2f713b535134824a67aec9f099be647e5593bbe3033a32dca96c164b1b0b85
7
+ data.tar.gz: b21cc5f7674752c33e4d55c3067f9f71ba372444d4ee497cc054a14293f89087232b55489e670aa7fafe891ce147a15924c1418009268c4875771d7a657c3431
data/.travis.yml CHANGED
@@ -13,3 +13,10 @@ rvm:
13
13
  matrix:
14
14
  allow_failures:
15
15
  - rvm: ruby-head
16
+ notifications:
17
+ webhooks:
18
+ urls:
19
+ - https://webhooks.gitter.im/e/177598ba2843dcdc1047
20
+ on_success: change
21
+ on_failure: always
22
+ on_start: false
data/CHANGELOG.md CHANGED
@@ -1,4 +1,26 @@
1
- ## v0.1.3 to-be-released
1
+ ## v0.2.0 2015-04-14
2
+
3
+ ### Added
4
+
5
+ * `:map_values` hash transformation (AMHOL)
6
+ * `:map_value` hash transformation (AMHOL)
7
+ * `:map_value` hash transformation (AMHOL)
8
+ * `:guard` function (AMHOL)
9
+ * `:is` type-check function (solnic)
10
+ * `Function#to_ast` for easy inspection (solnic)
11
+ * Ability to define module with custom functions that will be auto-registered (solnic + splattael)
12
+
13
+ ### Changed
14
+
15
+ * [BREAKING] `map_hash` renamed to `rename_keys`
16
+ * [BREAKING] `map_key` renamed to `map_value`
17
+ * [BREAKING] `map_array` no longer accepts multiple functions (AMHOL)
18
+ * All functions are now defined as module functions (solnic + splattael)
19
+ * Functions no longer create anonymous procs (solnic)
20
+
21
+ [Compare v0.1.3...v0.2.0](https://github.com/solnic/transproc/compare/v0.1.3...v0.2.0)
22
+
23
+ ## v0.1.3 2015-04-07
2
24
 
3
25
  ### Added
4
26
 
data/Gemfile CHANGED
@@ -3,10 +3,13 @@ source 'https://rubygems.org'
3
3
  gemspec
4
4
 
5
5
  group :test do
6
+ gem 'mutant'
7
+ gem 'mutant-rspec'
6
8
  gem 'codeclimate-test-reporter', require: nil
7
9
  end
8
10
 
9
11
  group :tools do
10
12
  gem 'byebug', platform: :mri
11
13
  gem 'benchmark-ips'
14
+ gem 'guard-rspec'
12
15
  end
data/README.md CHANGED
@@ -5,7 +5,7 @@
5
5
  [coveralls]: https://coveralls.io/r/solnic/transproc
6
6
  [inchpages]: http://inch-ci.org/github/solnic/transproc
7
7
 
8
- # Transproc
8
+ # Transproc [![Join the chat at https://gitter.im/solnic/transproc](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/solnic/transproc?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
9
9
 
10
10
  [![Gem Version](https://badge.fury.io/rb/transproc.svg)][gem]
11
11
  [![Build Status](https://travis-ci.org/solnic/transproc.svg?branch=master)][travis]
@@ -39,21 +39,39 @@ Or install it yourself as:
39
39
  require 'transproc/all'
40
40
 
41
41
  # compose transformation functions
42
- transformation = Transproc(:symbolize_keys) >> Transproc(:map_hash, user_name: :name))
42
+ include Transproc::Helper
43
43
 
44
- # call the function
45
- transformation['user_name' => 'Jane']
46
- # => {:name=>"Jane"}
47
-
48
- # or using a helper (no, it's not a good idea to include it here :))
49
- include Transproc::Composer
44
+ transformation = t(:map_array, t(:symbolize_keys) >> t(:rename_keys, user_name: :user))
45
+ transformation >>= t(:wrap, :address, [:city, :street, :zipcode])
50
46
 
51
- transformation = compose do |fns|
52
- fns << t(:symbolize_keys) << t(:map_hash, user_name: :name)
47
+ # call the function
48
+ transformation.call(
49
+ [
50
+ { 'user_name' => 'Jane',
51
+ 'city' => 'NYC',
52
+ 'street' => 'Street 1',
53
+ 'zipcode' => '123' }
54
+ ]
55
+ )
56
+ # => [{:user=>"Jane", :address=>{:city=>"NYC", :street=>"Street 1", :zipcode=>"123"}}]
57
+
58
+ # Define your own transformations easily
59
+ Transproc(:to_json, -> v { JSON.dump(v) })
60
+
61
+ Transproc(:to_json).call([{ name: 'Jane' }])
62
+ # => "[{\"name\":\"Jane\"}]"
63
+
64
+ # ...or create a module with custom transformations
65
+ module MyTransformations
66
+ extend Transproc::Functions
67
+
68
+ def load_json(v)
69
+ JSON.load(v)
70
+ end
53
71
  end
54
72
 
55
- transformation['user_name' => 'Jane']
56
- # => {:name=>"Jane"}
73
+ (Transproc(:load_json) >> Transproc(:symbolize_keys)).call('[{"name":"Jane"}]')
74
+ # => [{ :name => "Jane" }]
57
75
  ```
58
76
 
59
77
  ## Credits
data/lib/transproc.rb CHANGED
@@ -3,23 +3,78 @@ require 'transproc/function'
3
3
  require 'transproc/composer'
4
4
 
5
5
  module Transproc
6
- def self.register(*args, &block)
6
+ module_function
7
+
8
+ # Register a new function
9
+ #
10
+ # @example
11
+ # Transproc.register(:to_json, -> v { v.to_json })
12
+ #
13
+ # Transproc(:map_array, Transproc(:to_json))
14
+ #
15
+ #
16
+ # @return [Function]
17
+ #
18
+ # @api public
19
+ def register(*args, &block)
7
20
  name, fn = *args
8
21
  functions[name] = fn || block
9
22
  end
10
23
 
11
- def self.functions
24
+ # Get registered function with provided name
25
+ #
26
+ # @param [Symbol] name The name of the registered function
27
+ #
28
+ # @api private
29
+ def [](name)
30
+ functions.fetch(name)
31
+ end
32
+
33
+ # Function registry
34
+ #
35
+ # @api private
36
+ def functions
12
37
  @_functions ||= {}
13
38
  end
14
39
 
15
- def self.[](name)
16
- functions.fetch(name)
40
+ # Function container extension
41
+ #
42
+ # @example
43
+ # module MyTransformations
44
+ # extend Transproc::Functions
45
+ #
46
+ # def boom!(value)
47
+ # "#{value} BOOM!"
48
+ # end
49
+ # end
50
+ #
51
+ # Transproc(:boom!)['w00t!'] # => "w00t! BOOM!"
52
+ #
53
+ # @api public
54
+ module Functions
55
+ def method_added(meth)
56
+ module_function meth
57
+ Transproc.register(meth, method(meth))
58
+ end
17
59
  end
18
60
  end
19
61
 
62
+ # Access registered functions
63
+ #
64
+ # @example
65
+ # Transproc(:map_array, Transproc(:to_string))
66
+ #
67
+ # Transproc(:to_string) >> Transproc(-> v { v.upcase })
68
+ #
69
+ # @param [Symbol,Proc] fn The name of the registered function or an anonymous proc
70
+ # @param [Array] args Optional addition args that a given function may need
71
+ #
72
+ # @return [Function]
73
+ #
74
+ # @api public
20
75
  def Transproc(fn, *args)
21
76
  case fn
22
- when Proc then Transproc::Function.new(fn, args)
23
- when Symbol then Transproc::Function.new(Transproc[fn], args)
77
+ when Proc then Transproc::Function.new(fn, args: args)
78
+ when Symbol then Transproc::Function.new(Transproc[fn], args: args)
24
79
  end
25
80
  end
data/lib/transproc/all.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  require 'transproc'
2
2
 
3
3
  require 'transproc/coercions'
4
+ require 'transproc/conditional'
4
5
  require 'transproc/array'
5
6
  require 'transproc/hash'
6
7
  require 'transproc/recursion'
@@ -1,27 +1,102 @@
1
+ require 'transproc/hash'
2
+
1
3
  module Transproc
2
- register(:map_array) do |array, *fns|
3
- Transproc(:map_array!, *fns)[Array[*array]]
4
- end
4
+ # Transformation functions for Array objects
5
+ #
6
+ # @example
7
+ # require 'transproc/array'
8
+ #
9
+ # include Transproc::Helper
10
+ #
11
+ # fn = t(:map_array, t(:symbolize_keys)) >> t(:wrap, :address, [:city, :zipcode])
12
+ #
13
+ # fn.call(
14
+ # [
15
+ # { 'city' => 'Boston', 'zipcode' => '123' },
16
+ # { 'city' => 'NYC', 'zipcode' => '312' }
17
+ # ]
18
+ # )
19
+ # # => [{ city: 'Boston', zipcode: '123' }, { city: 'NYC', zipcode: '312' }]
20
+ #
21
+ # @api public
22
+ module ArrayTransformations
23
+ extend Functions
5
24
 
6
- register(:map_array!) do |array, *fns|
7
- fn = fns.size == 1 ? fns[0] : fns.reduce(:+)
8
- array.map! { |value| fn[value] }
9
- end
25
+ # Map array values using transformation function
26
+ #
27
+ # @example
28
+ #
29
+ # fn = Transproc(:map_array, -> v { v.upcase })
30
+ #
31
+ # fn.call ['foo', 'bar'] # => ["FOO", "BAR"]
32
+ #
33
+ # @param [Array] array The input array
34
+ # @param [Proc] fn The transformation function
35
+ #
36
+ # @return [Array]
37
+ #
38
+ # @api public
39
+ def map_array(array, fn)
40
+ map_array!(Array[*array], fn)
41
+ end
10
42
 
11
- register(:wrap) do |array, key, keys|
12
- Transproc(:map_array, Transproc(:nest, key, keys))[array]
13
- end
43
+ # Same as `map_array` but mutates the array
44
+ #
45
+ # @see ArrayTransformations.map_array
46
+ #
47
+ # @api public
48
+ def map_array!(array, fn)
49
+ array.map! { |value| fn[value] }
50
+ end
14
51
 
15
- register(:group) do |array, key, keys|
16
- grouped = Hash.new { |hash, key| hash[key] = [] }
17
- array.each do |hash|
18
- hash = hash.dup
19
- child = {}
20
- keys.each { |k| child[k] = hash.delete(k) }
21
- grouped[hash] << child
52
+ # Wrap array values using HashTransformations.nest function
53
+ #
54
+ # @example
55
+ # fn = Transproc(:wrap, :address, [:city, :zipcode])
56
+ #
57
+ # fn.call [{ city: 'NYC', zipcode: '123' }]
58
+ # # => [{ address: { city: 'NYC', zipcode: '123' } }]
59
+ #
60
+ # @param [Array] array The input array
61
+ # @param [Object] key The nesting root key
62
+ # @param [Object] keys The nesting value keys
63
+ #
64
+ # @return [Array]
65
+ #
66
+ # @api public
67
+ def wrap(array, key, keys)
68
+ map_array(array, Transproc(:nest, key, keys))
22
69
  end
23
- grouped.map do |root, children|
24
- root.merge(key => children)
70
+
71
+ # Group array values using provided root key and value keys
72
+ #
73
+ # @example
74
+ # fn = Transproc(:group, :tags, [:tag_name])
75
+ #
76
+ # fn.call [
77
+ # { task: 'Group it', tag: 'task' },
78
+ # { task: 'Group it', tag: 'important' }
79
+ # ]
80
+ # # => [{ task: 'Group it', tags: [{ tag: 'task' }, { tag: 'important' }]]
81
+ #
82
+ # @param [Array] array The input array
83
+ # @param [Object] key The nesting root key
84
+ # @param [Object] keys The nesting value keys
85
+ #
86
+ # @return [Array]
87
+ #
88
+ # @api public
89
+ def group(array, key, keys)
90
+ grouped = Hash.new { |h, k| h[k] = [] }
91
+ array.each do |hash|
92
+ hash = hash.dup
93
+ child = {}
94
+ keys.each { |k| child[k] = hash.delete(k) }
95
+ grouped[hash] << child
96
+ end
97
+ grouped.map do |root, children|
98
+ root.merge(key => children)
99
+ end
25
100
  end
26
101
  end
27
102
  end
@@ -4,42 +4,154 @@ require 'bigdecimal'
4
4
  require 'bigdecimal/util'
5
5
 
6
6
  module Transproc
7
- TRUE_VALUES = [true, 1, '1', 'on', 't', 'true', 'y', 'yes'].freeze
8
- FALSE_VALUES = [false, 0, '0', 'off', 'f', 'false', 'n', 'no'].freeze
7
+ # Coercion functions for common types
8
+ #
9
+ # @api public
10
+ module Coercions
11
+ extend Functions
9
12
 
10
- BOOLEAN_MAP = Hash[
11
- TRUE_VALUES.product([true]) + FALSE_VALUES.product([false])
12
- ].freeze
13
+ TRUE_VALUES = [true, 1, '1', 'on', 't', 'true', 'y', 'yes'].freeze
14
+ FALSE_VALUES = [false, 0, '0', 'off', 'f', 'false', 'n', 'no'].freeze
13
15
 
14
- register(:to_string) do |value|
15
- value.to_s
16
- end
16
+ BOOLEAN_MAP = Hash[
17
+ TRUE_VALUES.product([true]) + FALSE_VALUES.product([false])
18
+ ].freeze
17
19
 
18
- register(:to_integer) do |value|
19
- value.to_i
20
- end
20
+ # Coerce value into a string
21
+ #
22
+ # @example
23
+ # Transproc(:to_string)[1]
24
+ # # => "1"
25
+ #
26
+ # @param [Object] value The input value
27
+ #
28
+ # @return [String]
29
+ #
30
+ # @api public
31
+ def to_string(value)
32
+ value.to_s
33
+ end
21
34
 
22
- register(:to_float) do |value|
23
- value.to_f
24
- end
35
+ # Coerce value into a symbol
36
+ #
37
+ # @example
38
+ # Transproc(:to_symbol)['foo']
39
+ # # => :foo
40
+ #
41
+ # @param [Object] value The input value
42
+ #
43
+ # @return [Symbol]
44
+ #
45
+ # @api public
46
+ def to_symbol(value)
47
+ value.to_sym
48
+ end
25
49
 
26
- register(:to_decimal) do |value|
27
- value.to_d
28
- end
50
+ # Coerce value into a integer
51
+ #
52
+ # @example
53
+ # Transproc(:to_integer)['1']
54
+ # # => 1
55
+ #
56
+ # @param [Object] value The input value
57
+ #
58
+ # @return [Integer]
59
+ #
60
+ # @api public
61
+ def to_integer(value)
62
+ value.to_i
63
+ end
29
64
 
30
- register(:to_boolean) do |value|
31
- BOOLEAN_MAP.fetch(value)
32
- end
65
+ # Coerce value into a float
66
+ #
67
+ # @example
68
+ # Transproc(:to_float)['1.2']
69
+ # # => 1.2
70
+ #
71
+ # @param [Object] value The input value
72
+ #
73
+ # @return [Float]
74
+ #
75
+ # @api public
76
+ def to_float(value)
77
+ value.to_f
78
+ end
33
79
 
34
- register(:to_date) do |value|
35
- Date.parse(value)
36
- end
80
+ # Coerce value into a decimal
81
+ #
82
+ # @example
83
+ # Transproc(:to_decimal)[1.2]
84
+ # # => #<BigDecimal:7fca32acea50,'0.12E1',18(36)>
85
+ #
86
+ # @param [Object] value The input value
87
+ #
88
+ # @return [Decimal]
89
+ #
90
+ # @api public
91
+ def to_decimal(value)
92
+ value.to_d
93
+ end
37
94
 
38
- register(:to_time) do |value|
39
- Time.parse(value)
40
- end
95
+ # Coerce value into a boolean
96
+ #
97
+ # @example
98
+ # Transproc(:to_boolean)['true']
99
+ # # => true
100
+ # Transproc(:to_boolean)['f']
101
+ # # => false
102
+ #
103
+ # @param [Object] value The input value
104
+ #
105
+ # @return [TrueClass,FalseClass]
106
+ #
107
+ # @api public
108
+ def to_boolean(value)
109
+ BOOLEAN_MAP.fetch(value)
110
+ end
111
+
112
+ # Coerce value into a date
113
+ #
114
+ # @example
115
+ # Transproc(:to_date)['2015-04-14']
116
+ # # => #<Date: 2015-04-14 ((2457127j,0s,0n),+0s,2299161j)>
117
+ #
118
+ # @param [Object] value The input value
119
+ #
120
+ # @return [Date]
121
+ #
122
+ # @api public
123
+ def to_date(value)
124
+ Date.parse(value)
125
+ end
126
+
127
+ # Coerce value into a time
128
+ #
129
+ # @example
130
+ # Transproc(:to_time)['2015-04-14 12:01:45']
131
+ # # => 2015-04-14 12:01:45 +0200
132
+ #
133
+ # @param [Object] value The input value
134
+ #
135
+ # @return [Time]
136
+ #
137
+ # @api public
138
+ def to_time(value)
139
+ Time.parse(value)
140
+ end
41
141
 
42
- register(:to_datetime) do |value|
43
- DateTime.parse(value)
142
+ # Coerce value into a datetime
143
+ #
144
+ # @example
145
+ # Transproc(:to_datetime)['2015-04-14 12:01:45']
146
+ # # => #<DateTime: 2015-04-14T12:01:45+00:00 ((2457127j,43305s,0n),+0s,2299161j)>
147
+ #
148
+ # @param [Object] value The input value
149
+ #
150
+ # @return [DateTime]
151
+ #
152
+ # @api public
153
+ def to_datetime(value)
154
+ DateTime.parse(value)
155
+ end
44
156
  end
45
157
  end