inactive_support 1.0.0 → 1.1.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.
- data/README.md +6 -6
- data/lib/inactive_support/enumerable/consecutive_by.rb +38 -0
- data/lib/inactive_support/enumerable.rb +1 -0
- data/lib/inactive_support/hash/delete_blank.rb +10 -3
- data/lib/inactive_support/numeric/precision.rb +13 -13
- data/lib/inactive_support/object/identity.rb +1 -3
- data/lib/inactive_support/object/try.rb +4 -8
- data/lib/inactive_support/version.rb +1 -1
- data/spec/lib/enumerable_spec.rb +77 -0
- data/spec/lib/hash_spec.rb +100 -0
- metadata +33 -15
- checksums.yaml +0 -7
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# InactiveSupport
|
2
2
|
|
3
|
-
A collection of utilities for ruby projects.
|
3
|
+
A collection of utilities for ruby projects.
|
4
4
|
|
5
5
|
## Installation
|
6
6
|
|
@@ -21,22 +21,22 @@ Or install it yourself as:
|
|
21
21
|
### Object
|
22
22
|
#### #identity
|
23
23
|
returns self
|
24
|
-
|
24
|
+
|
25
25
|
[1,2,3,3,4,5,5].group_by(&:identity)
|
26
26
|
# => [[1], [2], [3,3], [4], [5,5]]
|
27
|
-
|
27
|
+
|
28
28
|
#### #try
|
29
29
|
send a message to the receiver and if it doesn't respond to the message, return nil
|
30
30
|
|
31
31
|
"".try(:some_method)
|
32
32
|
# => nil
|
33
|
-
|
33
|
+
|
34
34
|
#### #ctry
|
35
35
|
chained try, for methods with no arguments
|
36
36
|
|
37
37
|
"Somestring".ctry(:mb_chars, :downcase, :some_method)
|
38
38
|
# => nil
|
39
|
-
|
39
|
+
|
40
40
|
### Hash
|
41
41
|
#### #delete_blank
|
42
42
|
Deletes all key/value pairs where the value is an empty string/array/hash or nil.
|
@@ -50,7 +50,7 @@ groups objects by an attribute that is consecutive
|
|
50
50
|
|
51
51
|
[1,2,3,5,6,8,9].consecutive_by(&:identity)
|
52
52
|
# => [[1,2,3],[5,6],[8,9]]
|
53
|
-
|
53
|
+
|
54
54
|
|
55
55
|
## Contributing
|
56
56
|
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module Enumerable
|
3
|
+
def consecutive_by
|
4
|
+
sorted = sort { |a, b| _ordinal(yield(a)) <=> _ordinal(yield(b)) }
|
5
|
+
|
6
|
+
prev = sorted.first
|
7
|
+
|
8
|
+
sorted.slice_before do |cur|
|
9
|
+
prev, prev2 = cur, prev
|
10
|
+
_ordinal(yield(prev2)) + 1 != _ordinal(yield(prev))
|
11
|
+
end.to_a
|
12
|
+
end
|
13
|
+
|
14
|
+
def consecutive?(&block)
|
15
|
+
if block_given?
|
16
|
+
consecutive_by(&block).count == 1 && self.sorted?(&block)
|
17
|
+
else
|
18
|
+
consecutive_by(&:identity).count == 1 && self.sorted?(&block)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def sorted?
|
23
|
+
if block_given?
|
24
|
+
each_cons(2).all? do |a, b|
|
25
|
+
(_ordinal(yield(a)) <=> _ordinal(yield(b))) <= 0
|
26
|
+
end
|
27
|
+
else
|
28
|
+
each_cons(2).all? do |a, b|
|
29
|
+
(_ordinal(a).to_i <=> _ordinal(b).to_i) <= 0
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
def _ordinal(string)
|
36
|
+
string.to_s.gsub(/[a-zA-Z]/) { |c| c.ord }.to_i
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'inactive_support/enumerable/consecutive_by'
|
@@ -1,8 +1,15 @@
|
|
1
1
|
class Hash
|
2
|
-
# Deletes all key/value pairs where the value is empty string/array/hash or nil.
|
2
|
+
# Deletes all key/value pairs where the value is empty string/array/hash or nil.
|
3
3
|
def delete_blank
|
4
|
-
delete_if do |
|
5
|
-
(v.blank? && v != false)
|
4
|
+
delete_if do |_, v|
|
5
|
+
(v.blank? && v != false)
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
# Recursively deletes all key/value pairs where the value is empty string/array/hash or nil.
|
10
|
+
def deep_delete_blank
|
11
|
+
delete_if do |_, v|
|
12
|
+
(v.blank? && v != false) || v.instance_of?(Hash) && v.deep_delete_blank.empty?
|
6
13
|
end
|
7
14
|
end
|
8
15
|
end
|
@@ -1,20 +1,20 @@
|
|
1
|
+
# A more precise rounding. ~4 times slower than simple round
|
2
|
+
#
|
3
|
+
# 3.904605.round(2)
|
4
|
+
# # => 3.9
|
5
|
+
# 3.904605.precision(2)
|
6
|
+
# # => 3.91
|
7
|
+
#
|
8
|
+
# 37.9945.round(2)
|
9
|
+
# # => 37.99
|
10
|
+
# 37.9945.precision(2)
|
11
|
+
# # => 38.0
|
1
12
|
class Numeric
|
2
|
-
# A more precise rounding. ~4 times slower than simple round
|
3
|
-
#
|
4
|
-
# 3.904605.round(2)
|
5
|
-
# # => 3.9
|
6
|
-
# 3.904605.precision(2)
|
7
|
-
# # => 3.91
|
8
|
-
#
|
9
|
-
# 37.9945.round(2)
|
10
|
-
# # => 37.99
|
11
|
-
# 37.9945.precision(2)
|
12
|
-
# # => 38.0
|
13
13
|
def precision(precision = 0)
|
14
|
-
power = 10
|
14
|
+
power = 10**precision
|
15
15
|
|
16
16
|
if precision == 0
|
17
|
-
|
17
|
+
round
|
18
18
|
else
|
19
19
|
powered = self * power
|
20
20
|
|
@@ -1,5 +1,4 @@
|
|
1
1
|
class Object
|
2
|
-
|
3
2
|
# Credit goes to the active_support contributors
|
4
3
|
# https://github.com/rails/rails/blob/master/activesupport/lib/active_support/core_ext/object/try.rb
|
5
4
|
#
|
@@ -14,25 +13,23 @@ class Object
|
|
14
13
|
end
|
15
14
|
end
|
16
15
|
|
17
|
-
|
18
16
|
# Chained try allows writing
|
19
17
|
#
|
20
18
|
# str.ctry(:mb_chars, :downcase, :dasherize)
|
21
19
|
#
|
22
20
|
# instead of
|
23
|
-
#
|
21
|
+
#
|
24
22
|
# str.try(:mb_chars).try(:downcase).try(:dasherize)
|
25
23
|
#
|
26
|
-
# Only works for methods that don't take arguments.
|
24
|
+
# Only works for methods that don't take any arguments.
|
27
25
|
def ctry(*args)
|
28
26
|
first, *rest = args
|
29
27
|
if rest.any?
|
30
|
-
|
28
|
+
try(first).ctry(*rest)
|
31
29
|
else
|
32
|
-
|
30
|
+
try(first)
|
33
31
|
end
|
34
32
|
end
|
35
|
-
|
36
33
|
end
|
37
34
|
|
38
35
|
class NilClass
|
@@ -43,5 +40,4 @@ class NilClass
|
|
43
40
|
def ctry(*args)
|
44
41
|
nil
|
45
42
|
end
|
46
|
-
|
47
43
|
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'inactive_support/enumerable'
|
3
|
+
|
4
|
+
describe Enumerable do
|
5
|
+
let(:simple_man) { Struct.new(:name, :age) }
|
6
|
+
let(:mitko) { simple_man.new('Mitko', 10) }
|
7
|
+
let(:goshko) { simple_man.new('Goshko', 11) }
|
8
|
+
let(:krasi) { simple_man.new('Krasi', 13) }
|
9
|
+
let(:dedo) { simple_man.new('Dedo', 15) }
|
10
|
+
|
11
|
+
describe '.consecutive_by' do
|
12
|
+
it 'partitions lists by consecutive attribute' do
|
13
|
+
simple_people = [mitko, goshko, krasi, dedo]
|
14
|
+
|
15
|
+
simple_people.consecutive_by(&:age).should eq [[mitko, goshko], [krasi], [dedo]]
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'sorts by the given method before partitioning' do
|
19
|
+
simple_people = [goshko, krasi, dedo, mitko]
|
20
|
+
|
21
|
+
simple_people.consecutive_by(&:age).should eq [[mitko, goshko], [krasi], [dedo]]
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'works on bare arrays' do
|
25
|
+
ary = [1, 2, 3, 5, 7, 8, 11, 12]
|
26
|
+
|
27
|
+
ary.consecutive_by(&:identity).should eq [[1, 2, 3], [5], [7, 8], [11, 12]]
|
28
|
+
end
|
29
|
+
|
30
|
+
describe 'with letters somewhere in the number' do
|
31
|
+
|
32
|
+
it 'works if the letter is in the beginning' do
|
33
|
+
ary = %w(A1 A2 A3 A5 A6)
|
34
|
+
expected = [%w(A1 A2 A3), %w(A5 A6)]
|
35
|
+
|
36
|
+
expect(ary.consecutive_by(&:identity)).to eq expected
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'works if the letter is in the middle' do
|
40
|
+
ary = %w(12A12 12A13 12A14 12A16 12A17)
|
41
|
+
expected = [%w(12A12 12A13 12A14), %w(12A16 12A17)]
|
42
|
+
|
43
|
+
expect(ary.consecutive_by(&:identity)).to eq expected
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'differentiates letters' do
|
47
|
+
ary = %w(A1 B2 A3 A5 A6)
|
48
|
+
expected = [%w(A1), %w(A3), %w(A5 A6), %w(B2)]
|
49
|
+
|
50
|
+
expect(ary.consecutive_by(&:identity)).to eq expected
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
describe '.consecutive?' do
|
58
|
+
|
59
|
+
it 'returns true if the objects are consecutive by the given key' do
|
60
|
+
consecutive_people = [mitko, goshko]
|
61
|
+
non_consecutive_people = [mitko, goshko, krasi]
|
62
|
+
|
63
|
+
consecutive_people.consecutive?(&:age).should be_true
|
64
|
+
|
65
|
+
non_consecutive_people.consecutive?(&:age).should be_false
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'uses identity on the objects if no key is given' do
|
69
|
+
[1, 2, 3, 4].consecutive?.should be_true
|
70
|
+
[1, 2, 3, 5].consecutive?.should be_false
|
71
|
+
[2, 1, 3, 5].consecutive?.should be_false
|
72
|
+
[].consecutive?.should be_false
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
data/spec/lib/hash_spec.rb
CHANGED
@@ -74,4 +74,104 @@ describe Hash do
|
|
74
74
|
|
75
75
|
end
|
76
76
|
|
77
|
+
describe "#deep_delete_blank" do
|
78
|
+
|
79
|
+
it 'deletes nils' do
|
80
|
+
initial = {
|
81
|
+
id: 1,
|
82
|
+
name: {
|
83
|
+
first: nil,
|
84
|
+
middle: "Peter"
|
85
|
+
}
|
86
|
+
}
|
87
|
+
|
88
|
+
expected = {
|
89
|
+
id: 1,
|
90
|
+
name: {
|
91
|
+
middle: "Peter"
|
92
|
+
}
|
93
|
+
}
|
94
|
+
|
95
|
+
initial.deep_delete_blank.should eq expected
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'deletes empty strings' do
|
99
|
+
initial = {
|
100
|
+
id: 1,
|
101
|
+
name: {
|
102
|
+
first: "",
|
103
|
+
middle: "Peter"
|
104
|
+
}
|
105
|
+
}
|
106
|
+
|
107
|
+
expected = {
|
108
|
+
id: 1,
|
109
|
+
name: {
|
110
|
+
middle: "Peter"
|
111
|
+
}
|
112
|
+
}
|
113
|
+
|
114
|
+
initial.deep_delete_blank.should eq expected
|
115
|
+
end
|
116
|
+
|
117
|
+
it 'preserves false values' do
|
118
|
+
initial = {
|
119
|
+
id: 1,
|
120
|
+
name: {
|
121
|
+
first: false,
|
122
|
+
middle: "Peter"
|
123
|
+
}
|
124
|
+
}
|
125
|
+
|
126
|
+
expected = {
|
127
|
+
id: 1,
|
128
|
+
name: {
|
129
|
+
first: false,
|
130
|
+
middle: "Peter"
|
131
|
+
}
|
132
|
+
}
|
133
|
+
|
134
|
+
initial.deep_delete_blank.should eq expected
|
135
|
+
end
|
136
|
+
|
137
|
+
it 'deletes empty arrays' do
|
138
|
+
initial = {
|
139
|
+
id: 1,
|
140
|
+
name: {
|
141
|
+
addresses: [],
|
142
|
+
middle: "Peter"
|
143
|
+
}
|
144
|
+
}
|
145
|
+
|
146
|
+
expected = {
|
147
|
+
id: 1,
|
148
|
+
name: {
|
149
|
+
middle: "Peter"
|
150
|
+
}
|
151
|
+
}
|
152
|
+
|
153
|
+
initial.deep_delete_blank.should eq expected
|
154
|
+
|
155
|
+
end
|
156
|
+
it 'deletes empty hashes' do
|
157
|
+
initial = {
|
158
|
+
id: 1,
|
159
|
+
name: {
|
160
|
+
children: {},
|
161
|
+
middle: "Peter"
|
162
|
+
}
|
163
|
+
}
|
164
|
+
|
165
|
+
expected = {
|
166
|
+
id: 1,
|
167
|
+
name: {
|
168
|
+
middle: "Peter"
|
169
|
+
}
|
170
|
+
}
|
171
|
+
|
172
|
+
initial.deep_delete_blank.should eq expected
|
173
|
+
end
|
174
|
+
|
175
|
+
end
|
176
|
+
|
77
177
|
end
|
metadata
CHANGED
@@ -1,55 +1,62 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: inactive_support
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
|
+
prerelease:
|
5
6
|
platform: ruby
|
6
7
|
authors:
|
7
8
|
- gmitrev
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
|
-
date:
|
12
|
+
date: 2015-05-07 00:00:00.000000000 Z
|
12
13
|
dependencies:
|
13
14
|
- !ruby/object:Gem::Dependency
|
14
15
|
name: bundler
|
15
16
|
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
16
18
|
requirements:
|
17
|
-
- -
|
19
|
+
- - ~>
|
18
20
|
- !ruby/object:Gem::Version
|
19
21
|
version: '1.3'
|
20
22
|
type: :development
|
21
23
|
prerelease: false
|
22
24
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
23
26
|
requirements:
|
24
|
-
- -
|
27
|
+
- - ~>
|
25
28
|
- !ruby/object:Gem::Version
|
26
29
|
version: '1.3'
|
27
30
|
- !ruby/object:Gem::Dependency
|
28
31
|
name: rake
|
29
32
|
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
30
34
|
requirements:
|
31
|
-
- -
|
35
|
+
- - ! '>='
|
32
36
|
- !ruby/object:Gem::Version
|
33
37
|
version: '0'
|
34
38
|
type: :development
|
35
39
|
prerelease: false
|
36
40
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
37
42
|
requirements:
|
38
|
-
- -
|
43
|
+
- - ! '>='
|
39
44
|
- !ruby/object:Gem::Version
|
40
45
|
version: '0'
|
41
46
|
- !ruby/object:Gem::Dependency
|
42
47
|
name: rspec
|
43
48
|
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
44
50
|
requirements:
|
45
|
-
- -
|
51
|
+
- - ~>
|
46
52
|
- !ruby/object:Gem::Version
|
47
53
|
version: '2.6'
|
48
54
|
type: :development
|
49
55
|
prerelease: false
|
50
56
|
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
51
58
|
requirements:
|
52
|
-
- -
|
59
|
+
- - ~>
|
53
60
|
- !ruby/object:Gem::Version
|
54
61
|
version: '2.6'
|
55
62
|
description: A collection of utilities and extensions
|
@@ -59,14 +66,16 @@ executables: []
|
|
59
66
|
extensions: []
|
60
67
|
extra_rdoc_files: []
|
61
68
|
files:
|
62
|
-
-
|
63
|
-
-
|
69
|
+
- .gitignore
|
70
|
+
- .rspec
|
64
71
|
- Gemfile
|
65
72
|
- LICENSE.txt
|
66
73
|
- README.md
|
67
74
|
- Rakefile
|
68
75
|
- inactive_support.gemspec
|
69
76
|
- lib/inactive_support.rb
|
77
|
+
- lib/inactive_support/enumerable.rb
|
78
|
+
- lib/inactive_support/enumerable/consecutive_by.rb
|
70
79
|
- lib/inactive_support/hash.rb
|
71
80
|
- lib/inactive_support/hash/delete_blank.rb
|
72
81
|
- lib/inactive_support/numeric.rb
|
@@ -76,6 +85,7 @@ files:
|
|
76
85
|
- lib/inactive_support/object/identity.rb
|
77
86
|
- lib/inactive_support/object/try.rb
|
78
87
|
- lib/inactive_support/version.rb
|
88
|
+
- spec/lib/enumerable_spec.rb
|
79
89
|
- spec/lib/hash_spec.rb
|
80
90
|
- spec/lib/numeric_spec.rb
|
81
91
|
- spec/lib/object_spec.rb
|
@@ -83,28 +93,36 @@ files:
|
|
83
93
|
homepage: ''
|
84
94
|
licenses:
|
85
95
|
- MIT
|
86
|
-
metadata: {}
|
87
96
|
post_install_message:
|
88
97
|
rdoc_options: []
|
89
98
|
require_paths:
|
90
99
|
- lib
|
91
100
|
required_ruby_version: !ruby/object:Gem::Requirement
|
101
|
+
none: false
|
92
102
|
requirements:
|
93
|
-
- -
|
103
|
+
- - ! '>='
|
94
104
|
- !ruby/object:Gem::Version
|
95
105
|
version: '0'
|
106
|
+
segments:
|
107
|
+
- 0
|
108
|
+
hash: -4215888734430273764
|
96
109
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
110
|
+
none: false
|
97
111
|
requirements:
|
98
|
-
- -
|
112
|
+
- - ! '>='
|
99
113
|
- !ruby/object:Gem::Version
|
100
114
|
version: '0'
|
115
|
+
segments:
|
116
|
+
- 0
|
117
|
+
hash: -4215888734430273764
|
101
118
|
requirements: []
|
102
119
|
rubyforge_project:
|
103
|
-
rubygems_version:
|
120
|
+
rubygems_version: 1.8.23
|
104
121
|
signing_key:
|
105
|
-
specification_version:
|
122
|
+
specification_version: 3
|
106
123
|
summary: Snippets and useful stuff extracted from my projects
|
107
124
|
test_files:
|
125
|
+
- spec/lib/enumerable_spec.rb
|
108
126
|
- spec/lib/hash_spec.rb
|
109
127
|
- spec/lib/numeric_spec.rb
|
110
128
|
- spec/lib/object_spec.rb
|
checksums.yaml
DELETED
@@ -1,7 +0,0 @@
|
|
1
|
-
---
|
2
|
-
SHA1:
|
3
|
-
metadata.gz: 4fb7998869a0bba3ac1bb5605f625f65f2684c5d
|
4
|
-
data.tar.gz: 649925baa3a002f3d57f40b59d2d6c034ae061ac
|
5
|
-
SHA512:
|
6
|
-
metadata.gz: 74563eae66da697c6689860fa20beb6dffbda7e19295c6006443193b958e3f201488713de146afdfb1c8f27b34ef3d42a0c0e7bbdacd00d88ba1c31d46330a33
|
7
|
-
data.tar.gz: becbcbaa2fbbe33510ee8d9b6726e2d7efa37474c90edf5c30c19686d37ed1446406da7e2654e5514b4a195f00af359711ebc2aff93bf0ea4af1ed9800b06613
|