transproc 0.1.3 → 0.2.0

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