more_core_extensions 1.0.2 → 1.1.0

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