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 +4 -4
- data/CHANGELOG.adoc +7 -0
- data/README.adoc +7 -4
- data/lib/corefines/array.rb +60 -0
- data/lib/corefines/enumerable.rb +67 -0
- data/lib/corefines/string.rb +7 -3
- data/lib/corefines/version.rb +1 -1
- data/spec/array/wrap_spec.rb +50 -0
- data/spec/enumerable/many_spec.rb +66 -0
- data/spec/enumerable/map_to_spec.rb +15 -0
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ea0feea695c1bc742c15a3ca74b9e4aa98d1d632
|
4
|
+
data.tar.gz: cce9dd830c78ddec528b274c8a42119dd79bf51d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 36952b5e7ac736ae14986a44737fd7232a7ead39091ac4075b67b470dee862e260876511b757b316e326e95aa869fac6415adf6a7c775e7da9f34c72fe43bdcf
|
7
|
+
data.tar.gz: b70e5551f42ad5f19f44e65427bbf9d09c59b78a167e46e022ee1c33a65b81ae283fd497cd52b0acbd83ad5e416b8c3ba6932e0993e0900b47120d3a7cabd547
|
data/CHANGELOG.adoc
CHANGED
@@ -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].
|
data/README.adoc
CHANGED
@@ -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/
|
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}/
|
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.
|
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.
|
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]
|
data/lib/corefines/array.rb
CHANGED
@@ -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
|
data/lib/corefines/enumerable.rb
CHANGED
@@ -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
|
data/lib/corefines/string.rb
CHANGED
@@ -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
|
data/lib/corefines/version.rb
CHANGED
@@ -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.
|
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
|
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
|