corefines 1.6.0 → 1.7.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: 6ff01826fd1321effe7725bd8de106831ae6400c
4
- data.tar.gz: 6441dd63f2e8896861f092fce7c3001258aefdb1
3
+ metadata.gz: ea0feea695c1bc742c15a3ca74b9e4aa98d1d632
4
+ data.tar.gz: cce9dd830c78ddec528b274c8a42119dd79bf51d
5
5
  SHA512:
6
- metadata.gz: 4e3b8f57a51c0c947e9ae175481676b4b2c9423f687533a8d549069d39a3d35cd66b4830fff0430c83f821b15ac312b61db3e99d2de9271bae5dda2f181a0132
7
- data.tar.gz: e5d5affb24e366e957d40894bfaec32bd1cd1f59693816fd8777e2cddcf19f5981080a2d5abe0ab6a1e07398d0ad98fe7c7f3aa9ac3d82b39ef3eb9416875db4
6
+ metadata.gz: 36952b5e7ac736ae14986a44737fd7232a7ead39091ac4075b67b470dee862e260876511b757b316e326e95aa869fac6415adf6a7c775e7da9f34c72fe43bdcf
7
+ data.tar.gz: b70e5551f42ad5f19f44e65427bbf9d09c59b78a167e46e022ee1c33a65b81ae283fd497cd52b0acbd83ad5e416b8c3ba6932e0993e0900b47120d3a7cabd547
@@ -3,6 +3,13 @@
3
3
  :doc-base-url: http://www.rubydoc.info/github/jirutka/corefines/Corefines
4
4
  :issue-uri: {repo-uri}/issues
5
5
 
6
+ == 1.7.0 (2015-07-05)
7
+
8
+ * Add new refinement {doc-base-url}/Enumerable/MapTo[Enumerable#map_to].
9
+ * Add new refinement {doc-base-url}/Array/Wrap[Array#wrap].
10
+ * Add new refinement {doc-base-url}/Enumerable/Many[Enumerable#many?].
11
+
12
+
6
13
  == 1.6.0 (2015-05-16)
7
14
 
8
15
  * Add new refinement {doc-base-url}/String/Camelcase[String#camelcase].
@@ -11,14 +11,14 @@ ifdef::env-github[:idprefix: user-content-]
11
11
  :gh-name: jirutka/{gem-name}
12
12
  :gh-branch: master
13
13
  :badge-style: flat
14
- :doc-base-url: http://www.rubydoc.info/github/jirutka/corefines/Corefines
14
+ :doc-base-url: http://www.rubydoc.info/github/{gh-name}/{gh-branch}/Corefines
15
15
 
16
16
  ifdef::env-github[]
17
17
  image:https://img.shields.io/travis/{gh-name}/{gh-branch}.svg?style={badge-style}[Build Status, link="https://travis-ci.org/{gh-name}"]
18
18
  image:https://img.shields.io/codeclimate/coverage/github/{gh-name}.svg?style={badge-style}[Test Coverage, link="https://codeclimate.com/github/{gh-name}"]
19
19
  image:https://img.shields.io/codeclimate/github/{gh-name}.svg?style={badge-style}[Code Climate, link="https://codeclimate.com/github/{gh-name}"]
20
20
  image:https://img.shields.io/gem/v/{gem-name}.svg?style={badge-style}[Gem Version, link="https://rubygems.org/gems/{gem-name}"]
21
- image:https://img.shields.io/badge/yard-docs-blue.svg?style={badge-style}[Yard Docs, link="http://www.rubydoc.info/github/{gh-name}/frames"]
21
+ image:https://img.shields.io/badge/yard-docs-blue.svg?style={badge-style}[Yard Docs, link="http://www.rubydoc.info/github/{gh-name}/{gh-branch}"]
22
22
  endif::env-github[]
23
23
 
24
24
  Corefines is a collection of general purpose _refinements_ for extending the core capabilities of Ruby’s built-in classes.
@@ -41,12 +41,12 @@ TODO
41
41
  Add this line to your application’s Gemfile:
42
42
 
43
43
  [source]
44
- gem 'corefines', '~> 1.6'
44
+ gem 'corefines', '~> 1.7'
45
45
 
46
46
  or to your gemspec:
47
47
 
48
48
  [source]
49
- s.add_runtime_dependency 'corefines', '~> 1.6'
49
+ s.add_runtime_dependency 'corefines', '~> 1.7'
50
50
 
51
51
  and then execute:
52
52
 
@@ -132,9 +132,12 @@ Not ideal indeed, but probably the best of what we can achieve.
132
132
  * {doc-base-url}/Array[Array]
133
133
  ** {doc-base-url}/Array/Second[#second]
134
134
  ** {doc-base-url}/Array/Third[#third]
135
+ ** {doc-base-url}/Array/Wrap[.wrap]
135
136
  * {doc-base-url}/Enumerable[Enumerable]
136
137
  ** {doc-base-url}/Enumerable/IndexBy[#index_by]
138
+ ** {doc-base-url}/Enumerable/Many[#many?]
137
139
  ** {doc-base-url}/Enumerable/MapSend[#map_send]
140
+ ** {doc-base-url}/Enumerable/MapTo[#map_to]
138
141
  * {doc-base-url}/Hash[Hash]
139
142
  ** {doc-base-url}/Hash/OpAdd[#+]
140
143
  ** {doc-base-url}/Hash/Compact[#compact]
@@ -25,6 +25,66 @@ module Corefines
25
25
  end
26
26
  end
27
27
 
28
+ ##
29
+ # @!method self.wrap(object)
30
+ # Wraps its argument in an array unless it is already an array (or
31
+ # array-like).
32
+ #
33
+ # Specifically:
34
+ #
35
+ # * If the argument is +nil+ an empty list is returned.
36
+ # * Otherwise, if the argument responds to +to_ary+ it is invoked, and
37
+ # its result returned.
38
+ # * Otherwise, returns an array with the argument as its single element.
39
+ #
40
+ # @example
41
+ # Array.wrap(nil) # => []
42
+ # Array.wrap([1, 2, 3]) # => [1, 2, 3]
43
+ # Array.wrap(0) # => [0]
44
+ #
45
+ # This method is similar in purpose to <tt>Kernel#Array</tt>, but there
46
+ # are some differences:
47
+ #
48
+ # * If the argument responds to +to_ary+ the method is invoked.
49
+ # <tt>Kernel#Array</tt> moves on to try +to_a+ if the returned value is
50
+ # +nil+, but <tt>Array.wrap</tt> returns +nil+ right away.
51
+ # * If the returned value from +to_ary+ is neither +nil+ nor an +Array+
52
+ # object, <tt>Kernel#Array</tt> raises an exception, while
53
+ # <tt>Array.wrap</tt> does not, it just returns the value.
54
+ # * It does not call +to_a+ on the argument, but returns an empty array
55
+ # if argument is +nil+.
56
+ #
57
+ # The second point is easily explained with some enumerables:
58
+ #
59
+ # Array(foo: :bar) # => [[:foo, :bar]]
60
+ # Array.wrap(foo: :bar) # => [{:foo=>:bar}]
61
+ #
62
+ # There's also a related idiom that uses the splat operator:
63
+ #
64
+ # [*object]
65
+ #
66
+ # which returns <tt>[]</tt> for +nil+, but calls to
67
+ # <tt>Array(object)</tt> otherwise.
68
+ #
69
+ # The differences with <tt>Kernel#Array</tt> explained above apply to the
70
+ # rest of <tt>object</tt>s.
71
+ #
72
+ # @return [Array]
73
+ #
74
+ module Wrap
75
+ refine ::Array.singleton_class do
76
+ def wrap(object)
77
+ if object.nil?
78
+ []
79
+ elsif object.respond_to? :to_ary
80
+ object.to_ary || [object]
81
+ else
82
+ [object]
83
+ end
84
+ end
85
+ end
86
+ end
87
+
28
88
  include Support::AliasSubmodules
29
89
  end
30
90
  end
@@ -36,6 +36,47 @@ module Corefines
36
36
  end
37
37
  end
38
38
 
39
+ ##
40
+ # @!method many?
41
+ # Returns +true+ if the enumerable has more than one element.
42
+ #
43
+ # This method is functionally equivalent to <tt>enum.to_a.size > 1</tt>,
44
+ # or <tt>enum.select { ... }.length > 1</tt> when the block is given.
45
+ #
46
+ # @example
47
+ # [1].many? # => false
48
+ # [1, 2].many? # => true
49
+ # [1, 2, 3].many? # => true
50
+ # [1, nil].many? # => true
51
+ # [1, 2, 3].many? { |n| n > 2 } # => false
52
+ #
53
+ # @overload many?
54
+ # @return [Boolean] +true+ if the enumerable has more than one element.
55
+ #
56
+ # @overload many?(&block)
57
+ # @yield [obj] gives each element to the block.
58
+ # @return [Boolean] +true+ if the block returns a truthy value (i.e.
59
+ # other than +nil+ and +false+) more than once.
60
+ #
61
+ module Many
62
+ Support.classes_including_module(::Enumerable) do |klass|
63
+
64
+ refine klass do
65
+ def many?
66
+ cnt = 0
67
+ if block_given?
68
+ any? do |element|
69
+ cnt += 1 if yield element
70
+ cnt > 1
71
+ end
72
+ else
73
+ any? { (cnt += 1) > 1 }
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
79
+
39
80
  ##
40
81
  # @!method map_send(method_name, *args, &block)
41
82
  # Sends a message to each element and collects the result.
@@ -59,6 +100,32 @@ module Corefines
59
100
  end
60
101
  end
61
102
 
103
+ ##
104
+ # @!method map_to(klass)
105
+ # Maps each element of this _enum_ into the _klass_ via constructor.
106
+ #
107
+ # @example
108
+ # ['/tmp', '/var/tmp'].map_to(Pathname) # => [#<Pathname:/tmp>, #<Pathname:/var/tmp>]
109
+ #
110
+ # @param klass [#new] the klass to map each element to.
111
+ # @return [Enumerable] a new array with instances of the _klass_ for
112
+ # every element in _enum_.
113
+ #
114
+ module MapTo
115
+ Support.classes_including_module(::Enumerable) do |klass|
116
+
117
+ refine klass do
118
+ def map_to(klass)
119
+ map { |e| klass.new(e) }
120
+ end
121
+ end
122
+ end
123
+ end
124
+
62
125
  include Support::AliasSubmodules
126
+
127
+ class << self
128
+ alias_method :many?, :many
129
+ end
63
130
  end
64
131
  end
@@ -25,6 +25,10 @@ module Corefines
25
25
  # "camel::ca-se-y".camelcase(':', '-') # => "camelCaSeY"
26
26
  # "camel42case".camelcase(/[0-9]+/) # => "camelCase"
27
27
  #
28
+ # @param *separators [String, Regexp] the patterns used to determine
29
+ # where capitalization should occur. Defaults to <tt>/_+/</tt> and
30
+ # <tt>\s+</tt>.
31
+ #
28
32
  # @overload camelcase(first_letter, *separators)
29
33
  # @example
30
34
  # "camel case".camelcase(:upper) # => "CamelCase"
@@ -33,10 +37,10 @@ module Corefines
33
37
  # @param first_letter [:upper, :lower] desired case of the first
34
38
  # character of a word - +:upper+ to be upcased, or +:lower+ to
35
39
  # be downcased.
40
+ # @param *separators [String, Regexp] the patterns used to determine
41
+ # where capitalization should occur. Defaults to <tt>/_+/</tt> and
42
+ # <tt>\s+</tt>.
36
43
  #
37
- # @param *separators [String, Regexp] the patterns used to determine
38
- # where capitalization should occur. Defaults to <tt>/_+/</tt> and
39
- # <tt>\s+</tt>.
40
44
  # @return [String] a copy of the _str_ converted to camelcase.
41
45
  #
42
46
  module Camelcase
@@ -1,3 +1,3 @@
1
1
  module Corefines
2
- VERSION = '1.6.0'
2
+ VERSION = '1.7.0'
3
3
  end
@@ -0,0 +1,50 @@
1
+ describe Array do
2
+ using Corefines::Array::wrap
3
+
4
+ describe '.wrap' do
5
+
6
+ context "array" do
7
+ it "returns the given array unchanged" do
8
+ ary = ['foo', 'bar']
9
+ expect( Array.wrap(ary) ).to be ary
10
+ end
11
+ end
12
+
13
+ context "nil" do
14
+ it "returns an empty array" do
15
+ expect( Array.wrap(nil) ).to eq []
16
+ end
17
+ end
18
+
19
+ context "an object" do
20
+ it "returns it wrapped in an array" do
21
+ o = Object.new
22
+ expect( Array.wrap(o) ).to eq [o]
23
+ end
24
+ end
25
+
26
+ context "string" do
27
+ it "returns it wrapped in an array" do
28
+ expect( Array.wrap("foo\nbar") ).to eq ["foo\nbar"]
29
+ end
30
+ end
31
+
32
+ context "object with #to_ary" do
33
+
34
+ it "returns result of #to_ary" do
35
+ o = Class.new { def to_ary; ['foo', 'bar'] end }.new
36
+ expect( Array.wrap(o) ).to eq o.to_ary
37
+ end
38
+
39
+ it "returns wrapped if #to_ary returns nil" do
40
+ o = Class.new { def to_ary; nil end }.new
41
+ expect( Array.wrap(o) ).to eq [o]
42
+ end
43
+
44
+ it "doesn't complain if #to_ary doesn't return an array" do
45
+ o = Class.new { def to_ary; :not_an_array end }.new
46
+ expect( Array.wrap(o) ).to eq o.to_ary
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,66 @@
1
+ describe Enumerable do
2
+ using Corefines::Enumerable::many?
3
+
4
+ describe '#many?' do
5
+
6
+ shared_examples :without_block do |enum, expected|
7
+ context enum.class do
8
+ it { expect( enum.many? ).to be expected }
9
+ end
10
+ end
11
+
12
+ context "when empty" do
13
+ [ [], Set.new, {} ].each do |enum|
14
+ include_examples :without_block, enum, false
15
+ end
16
+ end
17
+
18
+ context "when one element" do
19
+ [ [42], Set.new([42]), {a: 42} ].each do |enum|
20
+ include_examples :without_block, enum, false
21
+ end
22
+ end
23
+
24
+ context "when two elements" do
25
+ [ [1, 2], Set.new([1, 2]), {a: 1, b: 2} ].each do |enum|
26
+ include_examples :without_block, enum, true
27
+ end
28
+ end
29
+
30
+ context "when two nil elements" do
31
+ [ [nil, nil], {a: nil, b: nil} ].each do |enum|
32
+ include_examples :without_block, enum, true
33
+ end
34
+ end
35
+
36
+ context "when more than two elements" do
37
+ [ [1, 2, 3], Set.new([1, 2, 3]), {a: 1, b: 2, c: 3} ].each do |enum|
38
+ include_examples :without_block, enum, true
39
+ end
40
+ end
41
+
42
+
43
+ context "with block" do
44
+
45
+ context "that yields true for one element" do
46
+ context Array do
47
+ it { expect( [1, 2].many? { |n| n > 1 } ).to eq false }
48
+ end
49
+
50
+ context Hash do
51
+ it { expect( {a: 1, b: 2}.many? { |k, v| v > 1 } ).to eq false }
52
+ end
53
+ end
54
+
55
+ context "that yield true for two elements" do
56
+ context Array do
57
+ it { expect( [1, 2].many? { |n| n > 0 } ).to eq true }
58
+ end
59
+
60
+ context Hash do
61
+ it { expect( {a: 1, b: 2}.many? { |k, v| k.is_a?(Symbol) } ).to eq true }
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,15 @@
1
+ require 'pathname'
2
+
3
+ describe Enumerable do
4
+ using Corefines::Enumerable::map_to
5
+
6
+ describe '#map_to' do
7
+
8
+ context Array do
9
+ it "creates instance of the klass for every element and collects the result" do
10
+ ary = ['/tmp', '/var/tmp']
11
+ expect( ary.map_to(Pathname) ).to eq ary.map { |e| Pathname.new(e) }
12
+ end
13
+ end
14
+ end
15
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: corefines
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.6.0
4
+ version: 1.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jakub Jirutka
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-05-16 00:00:00.000000000 Z
11
+ date: 2015-07-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: asciidoctor
@@ -122,8 +122,11 @@ files:
122
122
  - lib/corefines/version.rb
123
123
  - spec/array/second_spec.rb
124
124
  - spec/array/third_spec.rb
125
+ - spec/array/wrap_spec.rb
125
126
  - spec/enumerable/index_by_spec.rb
127
+ - spec/enumerable/many_spec.rb
126
128
  - spec/enumerable/map_send_spec.rb
129
+ - spec/enumerable/map_to_spec.rb
127
130
  - spec/hash/compact_spec.rb
128
131
  - spec/hash/except_spec.rb
129
132
  - spec/hash/only_spec.rb