more_core_extensions 1.0.2 → 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.
@@ -0,0 +1,21 @@
1
+ require 'active_support/core_ext/object/blank'
2
+
3
+ module MoreCoreExtensions
4
+ module ArrayDeletes
5
+ # Deletes all items where the value is nil
6
+ #
7
+ # [1, [], nil].delete_nils # => [1, []]
8
+ def delete_nils
9
+ delete_if { |i| i.nil? }
10
+ end
11
+
12
+ # Deletes all items where the value is blank
13
+ #
14
+ # [1, [], nil].delete_blanks # => [1]
15
+ def delete_blanks
16
+ delete_if { |i| i.blank? }
17
+ end
18
+ end
19
+ end
20
+
21
+ Array.send(:include, MoreCoreExtensions::ArrayDeletes)
@@ -29,6 +29,18 @@ module MoreCoreExtensions
29
29
  def include_all?(*items)
30
30
  (items - self).empty?
31
31
  end
32
+
33
+ #
34
+ # Returns whether the Array has a value at the index.
35
+ #
36
+ # [1, 2, 3].includes_index?(-4) #=> false
37
+ # [1, 2, 3].includes_index?(-3) #=> true
38
+ # [1, 2, 3].includes_index?(1) #=> true
39
+ # [1, 2, 3].includes_index?(2) #=> true
40
+ # [1, 2, 3].includes_index?(3) #=> false
41
+ def includes_index?(index)
42
+ (-self.length...self.length).cover?(index)
43
+ end
32
44
  end
33
45
  end
34
46
 
@@ -0,0 +1,15 @@
1
+ require_relative '../shared/nested'
2
+
3
+ module MoreCoreExtensions
4
+ module ArrayNested
5
+ include MoreCoreExtensions::Shared::Nested
6
+ extend MoreCoreExtensions::Shared::Nested
7
+
8
+ def delete_blank_paths
9
+ self.each { |v| v.delete_blank_paths if v.respond_to?(:delete_blank_paths) }
10
+ self.delete_blanks
11
+ end
12
+ end
13
+ end
14
+
15
+ Array.send(:include, MoreCoreExtensions::ArrayNested)
@@ -1,5 +1,7 @@
1
+ require 'more_core_extensions/core_ext/array/deletes'
1
2
  require 'more_core_extensions/core_ext/array/duplicates'
2
3
  require 'more_core_extensions/core_ext/array/inclusions'
4
+ require 'more_core_extensions/core_ext/array/nested'
3
5
  require 'more_core_extensions/core_ext/array/random'
4
6
  require 'more_core_extensions/core_ext/array/stretch'
5
7
  require 'more_core_extensions/core_ext/array/tableize'
@@ -1,59 +1,13 @@
1
+ require_relative '../shared/nested'
2
+
1
3
  module MoreCoreExtensions
2
4
  module HashNested
3
- def fetch_path(*args)
4
- args = args.first if args.length == 1 && args.first.kind_of?(Array)
5
- raise ArgumentError, "must pass at least one key" if args.empty?
6
-
7
- child = self[args.first]
8
- return child if args.length == 1
9
- return nil unless child.kind_of?(Hash)
10
- return child.fetch_path(args[1..-1])
11
- end
12
-
13
- def has_key_path?(*args)
14
- args = args.first if args.length == 1 && args.first.kind_of?(Array)
15
- raise ArgumentError, "must pass at least one key" if args.empty?
16
-
17
- key = args.first
18
- has_child = self.has_key?(key)
19
- return has_child if args.length == 1
20
-
21
- child = self[key]
22
- return false unless child.kind_of?(Hash)
23
- return child.has_key_path?(args[1..-1])
24
- end
25
- alias include_path? has_key_path?
26
- alias key_path? has_key_path?
27
- alias member_path? has_key_path?
28
-
29
- def store_path(*args)
30
- raise ArgumentError, "must pass at least one key, and a value" if args.length < 2
31
- value = args.pop
32
- args = args.first if args.length == 1 && args.first.kind_of?(Array)
33
-
34
- key = args.first
35
- if args.length == 1
36
- self[key] = value
37
- else
38
- child = self[key]
39
- unless child.kind_of?(Hash)
40
- self[key] = self.class.new
41
- child = self[key]
42
- end
43
- child.store_path(args[1..-1], value)
44
- end
45
- end
46
-
47
- def delete_path(*args)
48
- args = args.first if args.length == 1 && args.first.kind_of?(Array)
49
- raise ArgumentError, "must pass at least one key" if args.empty?
5
+ include MoreCoreExtensions::Shared::Nested
6
+ extend MoreCoreExtensions::Shared::Nested
50
7
 
51
- key = args.first
52
- if args.length == 1 || !(child = self[key]).kind_of?(Hash)
53
- self.delete(key)
54
- else
55
- child.delete_path(args[1..-1])
56
- end
8
+ def delete_blank_paths
9
+ self.each_value { |v| v.delete_blank_paths if v.respond_to?(:delete_blank_paths) }
10
+ self.delete_blanks
57
11
  end
58
12
  end
59
13
  end
@@ -0,0 +1,83 @@
1
+ module MoreCoreExtensions
2
+ module Shared
3
+ module Nested
4
+
5
+ def delete_path(*args)
6
+ args = args.first if args.length == 1 && args.first.kind_of?(Array)
7
+ raise ArgumentError, "must pass at least one key" if args.empty?
8
+
9
+ key = args.first
10
+ raise ArgumentError, "must be a number" if self.kind_of?(Array) && !key.kind_of?(Numeric)
11
+
12
+ child = self[key]
13
+ if args.length == 1 || !child.respond_to?(:delete_path)
14
+ self.kind_of?(Array) ? self.delete_at(key) : self.delete(key)
15
+ else
16
+ child.delete_path(args[1..-1])
17
+ end
18
+ end
19
+
20
+ def fetch_path(*args)
21
+ args = args.first if args.length == 1 && args.first.kind_of?(Array)
22
+ raise ArgumentError, "must pass at least one key" if args.empty?
23
+
24
+ key = args.first
25
+ raise ArgumentError, "must be a number" if self.kind_of?(Array) && !key.kind_of?(Numeric)
26
+
27
+ child = self[key]
28
+ return child if args.length == 1
29
+ return nil unless child.respond_to?(:fetch_path)
30
+ return child.fetch_path(args[1..-1])
31
+ end
32
+
33
+ def has_key_path?(*args)
34
+ args = args.first if args.length == 1 && args.first.kind_of?(Array)
35
+ raise ArgumentError, "must pass at least one key" if args.empty?
36
+
37
+ key = args.first
38
+ raise ArgumentError, "must be a number" if self.kind_of?(Array) && !key.kind_of?(Numeric)
39
+
40
+ has_child = self.kind_of?(Array) ? self.includes_index?(key) : self.has_key?(key)
41
+ return has_child if args.length == 1
42
+
43
+ child = self[key]
44
+ return false unless child.respond_to?(:has_key_path?)
45
+ return child.has_key_path?(args[1..-1])
46
+ end
47
+ alias include_path? has_key_path?
48
+ alias key_path? has_key_path?
49
+ alias member_path? has_key_path?
50
+
51
+ def store_path(*args)
52
+ raise ArgumentError, "must pass at least one key, and a value" if args.length < 2
53
+ value = args.pop
54
+ args = args.first if args.length == 1 && args.first.kind_of?(Array)
55
+
56
+ key = args.first
57
+ raise ArgumentError, "must be a number" if self.kind_of?(Array) && !key.kind_of?(Numeric)
58
+
59
+ if args.length == 1
60
+ self[key] = value
61
+ else
62
+ child = self[key]
63
+ unless child.respond_to?(:store_path)
64
+ self[key] = self.class.new
65
+ child = self[key]
66
+ end
67
+ child.store_path(args[1..-1].push, value)
68
+ end
69
+ end
70
+
71
+ def find_path(val)
72
+ self.each_with_index do |v, k|
73
+ k, v = v if self.kind_of?(Hash)
74
+ return [k] if v == val
75
+
76
+ c = v.respond_to?(:find_path) ? v.find_path(val) : []
77
+ return c.unshift(k) unless c.blank?
78
+ end
79
+ []
80
+ end
81
+ end
82
+ end
83
+ end
@@ -1,3 +1,3 @@
1
1
  module MoreCoreExtensions
2
- VERSION = "1.0.2"
2
+ VERSION = "1.1.0"
3
3
  end
@@ -0,0 +1,17 @@
1
+ require_relative "../../spec_helper"
2
+
3
+ describe Array do
4
+ it "#delete_nils" do
5
+ [].delete_nils.should == []
6
+ [1].delete_nils.should == [1]
7
+ [nil].delete_nils.should == []
8
+ [1, [], nil].delete_nils.should == [1, []]
9
+ end
10
+
11
+ it "#delete_blanks" do
12
+ [].delete_blanks.should == []
13
+ [1].delete_blanks.should == [1]
14
+ [nil].delete_blanks.should == []
15
+ [1, [], nil].delete_blanks.should == [1]
16
+ end
17
+ end
@@ -30,4 +30,12 @@ describe Array do
30
30
  ['1', '2', '3'].include_all?('1', '4').should be_false
31
31
  ['1', '2', '3'].include_all?('4', '5').should be_false
32
32
  end
33
+
34
+ it "#includes_index?" do
35
+ [1, 2, 3].includes_index?(-4).should be_false
36
+ [1, 2, 3].includes_index?(-3).should be_true
37
+ [1, 2, 3].includes_index?(1).should be_true
38
+ [1, 2, 3].includes_index?(2).should be_true
39
+ [1, 2, 3].includes_index?(3).should be_false
40
+ end
33
41
  end
@@ -0,0 +1,185 @@
1
+ require_relative "../../spec_helper"
2
+
3
+ shared_examples_for "core_ext/array/nested will not modify arguments" do |meth|
4
+ it "will not modify arguments" do
5
+ args = (meth == :store_path ? [1] : [])
6
+
7
+ key = [3, 0, 1, 2]
8
+ key2 = key.dup
9
+ array.send(meth, key2, *args)
10
+ key2.should == key
11
+
12
+ key = [4, 0, 1]
13
+ key2 = key.dup
14
+ array.send(meth, key2, *args)
15
+ key2.should == key
16
+ end
17
+ end
18
+
19
+ shared_examples_for "core_ext/array/nested" do
20
+ context '#fetch_path' do
21
+ it "with various values" do
22
+ array.fetch_path(0).should == 1
23
+ array.fetch_path(1).should == []
24
+ array.fetch_path(1, 0).should be_nil
25
+ array.fetch_path(1, 0, 1).should be_nil
26
+ array.fetch_path(2).should == [2]
27
+ array.fetch_path(2, 0).should == 2
28
+ array.fetch_path(-4, 0).should == 2
29
+ array.fetch_path(2, 0, 1).should be_nil
30
+ array.fetch_path(3, 0, 0, 0).should == 3
31
+ array.fetch_path(3, 0, 1, 999).should be_nil
32
+ array.fetch_path(3, 0, 1, 2, 3).should be_nil
33
+ array.fetch_path(4).should == [nil, nil, nil, nil]
34
+ array.fetch_path(4, 0).should be_nil
35
+ array.fetch_path(4, 0, 1).should be_nil
36
+ array.fetch_path(5).should == []
37
+ array.fetch_path(5, 0).should be_nil
38
+ array.fetch_path(5, 0, 1).should be_nil
39
+ end
40
+
41
+ it "with a nil value should raise ArgumentError" do
42
+ lambda { array.fetch_path(nil) }.should raise_error(ArgumentError)
43
+ lambda { array.fetch_path(3, nil, 0) }.should raise_error(ArgumentError)
44
+ end
45
+
46
+ it "with invalid values" do
47
+ lambda { array.fetch_path }.should raise_error(ArgumentError)
48
+ end
49
+
50
+ include_examples "core_ext/array/nested will not modify arguments", :fetch_path
51
+ end
52
+
53
+ context "#store_path" do
54
+ it "on an empty array" do
55
+ a = described_class.new
56
+ a.store_path(0, 1)
57
+ a.should == [1]
58
+
59
+ a = described_class.new
60
+ a.store_path(1, 0, 2)
61
+ a.should == [nil, [2]]
62
+ end
63
+
64
+ it "on an existing array" do
65
+ array.store_path(1, 0, 2)
66
+ array[1].should == [2]
67
+ array.store_path(2, 0, 3)
68
+ array[2].should == [3]
69
+ array.store_path(-4, 0, 3)
70
+ array[2].should == [3]
71
+ end
72
+
73
+ it "on an existing item that is not a array" do
74
+ array.store_path(0, 2)
75
+ array[0].should == 2
76
+ array.store_path(0, 0, 3)
77
+ array[0].should == [3]
78
+ end
79
+
80
+ it "with an array of args" do
81
+ a = described_class.new
82
+ a.store_path([3, 0, 1, 2], 3)
83
+ a.should == [nil, nil, nil, [[nil, [nil, nil, 3]]]]
84
+ end
85
+
86
+ it "with a nil value" do
87
+ a = described_class.new
88
+ a.store_path(0, 1, nil)
89
+ a.should == [[nil, nil]]
90
+ end
91
+
92
+ it "with an Array value" do
93
+ a = described_class.new
94
+ a.store_path(0, 1, [2, 3])
95
+ a.should == [[nil, [2, 3]]]
96
+ end
97
+
98
+ it "with a Hash value" do
99
+ a = described_class.new
100
+ a.store_path(0, 1, {2 => 3})
101
+ a.should == [[nil, {2 => 3}]]
102
+ end
103
+
104
+ it "with invalid values" do
105
+ lambda { described_class.new.store_path }.should raise_error(ArgumentError)
106
+ lambda { described_class.new.store_path(1) }.should raise_error(ArgumentError)
107
+ end
108
+
109
+ include_examples "core_ext/array/nested will not modify arguments", :store_path
110
+ end
111
+
112
+ context '#has_key_path?' do
113
+ it "with various values" do
114
+ array.has_key_path?(0).should be_true
115
+ array.has_key_path?(1).should be_true
116
+ array.has_key_path?(1, 0).should be_false
117
+ array.has_key_path?(1, 0, 1).should be_false
118
+ array.has_key_path?(2).should be_true
119
+ array.has_key_path?(2, 0).should be_true
120
+ array.has_key_path?(2, 0, 1).should be_false
121
+ array.has_key_path?(3, 0, 1, 2).should be_false
122
+ array.has_key_path?(3, 0, 1, 999).should be_false
123
+ array.has_key_path?(3, 0, 1, 2, 3).should be_false
124
+ array.has_key_path?(4).should be_true
125
+ array.has_key_path?(4, 0).should be_true
126
+ array.has_key_path?(4, 0, 1).should be_false
127
+ array.has_key_path?(5).should be_true
128
+ array.has_key_path?(5, 0).should be_false
129
+ array.has_key_path?(5, 0, 1).should be_false
130
+ end
131
+
132
+ it "with a nil value" do
133
+ lambda { array.fetch_path(nil) }.should raise_error(ArgumentError)
134
+ lambda { array.fetch_path(3, nil, 0) }.should raise_error(ArgumentError)
135
+ end
136
+
137
+ it "with invalid values" do
138
+ lambda { array.has_key_path? }.should raise_error(ArgumentError)
139
+ end
140
+
141
+ include_examples "core_ext/array/nested will not modify arguments", :has_key_path?
142
+ end
143
+
144
+ context "#delete_path" do
145
+ it "on a nested array" do
146
+ array.delete_path(3, 0, 0, 0)
147
+ array[3].should == [[[]]]
148
+ end
149
+
150
+ it "with an invalid path" do
151
+ array.delete_path(3, 0, 5)
152
+ array[3].should == [[[3]]]
153
+ end
154
+
155
+ include_examples "core_ext/array/nested will not modify arguments", :delete_path
156
+ end
157
+
158
+ it "#delete_blank_paths" do
159
+ array.delete_blank_paths.should == [1, [2], [[[3]]]]
160
+ end
161
+
162
+ context "#find_path" do
163
+ it "with a real value" do
164
+ array.find_path(3).should == [3, 0, 0, 0]
165
+ end
166
+
167
+ it "with non-existent value" do
168
+ array.find_path(42).should == []
169
+ end
170
+ end
171
+ end
172
+
173
+ describe Array do
174
+ let(:array) do
175
+ [ 1,
176
+ [],
177
+ [2],
178
+ [[[3]]],
179
+ Array.new(4),
180
+ described_class.new { |i| i = described_class.new }
181
+ ]
182
+ end
183
+
184
+ include_examples "core_ext/array/nested"
185
+ end
@@ -38,12 +38,16 @@ shared_examples_for "core_ext/hash/nested" do
38
38
  end
39
39
 
40
40
  it "with a nil value" do
41
- hash.fetch_path(nil).should be_nil
41
+ hash.fetch_path(nil).should == {nil => 7}
42
42
  hash.fetch_path("d", nil, "d1").should be_nil
43
43
  hash.fetch_path("e", nil).should == 4
44
44
  hash.fetch_path("e", nil, "e1").should be_nil
45
45
  end
46
46
 
47
+ it "with array key" do
48
+ hash.fetch_path([["h", "i"]]).should == 8
49
+ end
50
+
47
51
  it "with invalid values" do
48
52
  lambda { hash.fetch_path }.should raise_error(ArgumentError)
49
53
  end
@@ -76,10 +80,10 @@ shared_examples_for "core_ext/hash/nested" do
76
80
  hash["a"].should == {"a1" => 3}
77
81
  end
78
82
 
79
- it "with an array of keys" do
83
+ it "with an array key" do
80
84
  h = described_class.new
81
- h.store_path(["d", "d1", "d2", "d3"], 3)
82
- h.should == {"d" => {"d1" => {"d2" => {"d3" => 3}}}}
85
+ h.store_path([["d", "d1"], ["d2", "d3"]], 3)
86
+ h.should == {["d", "d1"] => {["d2", "d3"] => 3}}
83
87
  end
84
88
 
85
89
  it "with a nil value" do
@@ -129,7 +133,7 @@ shared_examples_for "core_ext/hash/nested" do
129
133
  end
130
134
 
131
135
  it "with a nil value" do
132
- hash.has_key_path?(nil).should be_false
136
+ hash.has_key_path?(nil).should be_true
133
137
  hash.has_key_path?("d", nil, "d1").should be_false
134
138
  hash.has_key_path?("e", nil).should be_false
135
139
  hash.has_key_path?("e", nil, "e1").should be_false
@@ -143,8 +147,32 @@ shared_examples_for "core_ext/hash/nested" do
143
147
  end
144
148
 
145
149
  context "#delete_path" do
150
+ it "on a nested hash" do
151
+ hash.delete_path("d", "d1", "d2", "d3")
152
+ hash["d"].should == {"d1"=>{"d2"=>{}}}
153
+ end
154
+
155
+ it "with an invalid path" do
156
+ hash.delete_path("d", "d1", :d)
157
+ hash["d"].should == {"d1"=>{"d2"=>{"d3"=>3}}}
158
+ end
159
+
146
160
  include_examples "core_ext/hash/nested will not modify arguments", :delete_path
147
161
  end
162
+
163
+ it "#delete_blank_paths" do
164
+ hash.delete_blank_paths.should == {"a"=>1, "c"=>{"c1"=>2}, "d"=>{"d1"=>{"d2"=>{"d3"=>3}}}, nil=>{nil=>7}, ["h", "i"]=>8}
165
+ end
166
+
167
+ context "#find_path" do
168
+ it "with a real value" do
169
+ hash.find_path(3).should == ["d", "d1", "d2", "d3"]
170
+ end
171
+
172
+ it "with non-existent value" do
173
+ hash.find_path(42).should == []
174
+ end
175
+ end
148
176
  end
149
177
 
150
178
  describe Hash do
@@ -155,7 +183,9 @@ describe Hash do
155
183
  "c" => {"c1" => 2},
156
184
  "d" => {"d1" => {"d2" => {"d3" => 3}}},
157
185
  "e" => Hash.new(4),
158
- "f" => Hash.new { |h, k| h[k] = Hash.new }
186
+ "f" => Hash.new { |h, k| h[k] = Hash.new },
187
+ nil => {nil => 7},
188
+ ["h", "i"] => 8
159
189
  }
160
190
  end
161
191
 
@@ -171,7 +201,9 @@ describe HashWithIndifferentAccess do
171
201
  "c" => {"c1" => 2},
172
202
  "d" => {"d1" => {"d2" => {"d3" => 3}}},
173
203
  "e" => Hash.new(4),
174
- "f" => described_class.new { |h, k| h[k] = described_class.new }
204
+ "f" => described_class.new { |h, k| h[k] = described_class.new },
205
+ nil => {nil => 7},
206
+ ["h", "i"] => 8
175
207
  )
176
208
 
177
209
  # NOTE: "f" has to be initialized in that way due to a bug in
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: more_core_extensions
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-09-09 00:00:00.000000000 Z
12
+ date: 2013-10-04 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -109,21 +109,26 @@ files:
109
109
  - lib/more_core_extensions.rb
110
110
  - lib/more_core_extensions/all.rb
111
111
  - lib/more_core_extensions/core_ext/array.rb
112
+ - lib/more_core_extensions/core_ext/array/deletes.rb
112
113
  - lib/more_core_extensions/core_ext/array/duplicates.rb
113
114
  - lib/more_core_extensions/core_ext/array/inclusions.rb
115
+ - lib/more_core_extensions/core_ext/array/nested.rb
114
116
  - lib/more_core_extensions/core_ext/array/random.rb
115
117
  - lib/more_core_extensions/core_ext/array/stretch.rb
116
118
  - lib/more_core_extensions/core_ext/array/tableize.rb
117
119
  - lib/more_core_extensions/core_ext/hash.rb
118
120
  - lib/more_core_extensions/core_ext/hash/deletes.rb
119
121
  - lib/more_core_extensions/core_ext/hash/nested.rb
122
+ - lib/more_core_extensions/core_ext/shared/nested.rb
120
123
  - lib/more_core_extensions/core_ext/string.rb
121
124
  - lib/more_core_extensions/core_ext/string/formats.rb
122
125
  - lib/more_core_extensions/core_ext/string/hex_dump.rb
123
126
  - lib/more_core_extensions/version.rb
124
127
  - more_core_extensions.gemspec
128
+ - spec/core_ext/array/deletes_spec.rb
125
129
  - spec/core_ext/array/duplicates_spec.rb
126
130
  - spec/core_ext/array/inclusions_spec.rb
131
+ - spec/core_ext/array/nested_spec.rb
127
132
  - spec/core_ext/array/stretch_spec.rb
128
133
  - spec/core_ext/array/tableize_spec.rb
129
134
  - spec/core_ext/hash/deletes_spec.rb
@@ -144,18 +149,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
144
149
  - - ! '>='
145
150
  - !ruby/object:Gem::Version
146
151
  version: '0'
147
- segments:
148
- - 0
149
- hash: 1712580559107520706
150
152
  required_rubygems_version: !ruby/object:Gem::Requirement
151
153
  none: false
152
154
  requirements:
153
155
  - - ! '>='
154
156
  - !ruby/object:Gem::Version
155
157
  version: '0'
156
- segments:
157
- - 0
158
- hash: 1712580559107520706
159
158
  requirements: []
160
159
  rubyforge_project:
161
160
  rubygems_version: 1.8.25
@@ -164,8 +163,10 @@ specification_version: 3
164
163
  summary: MoreCoreExtensions are a set of core extensions beyond those provided by
165
164
  ActiveSupport.
166
165
  test_files:
166
+ - spec/core_ext/array/deletes_spec.rb
167
167
  - spec/core_ext/array/duplicates_spec.rb
168
168
  - spec/core_ext/array/inclusions_spec.rb
169
+ - spec/core_ext/array/nested_spec.rb
169
170
  - spec/core_ext/array/stretch_spec.rb
170
171
  - spec/core_ext/array/tableize_spec.rb
171
172
  - spec/core_ext/hash/deletes_spec.rb