robsharp-extlib 0.9.15

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.
Files changed (73) hide show
  1. data/.autotest +21 -0
  2. data/.document +5 -0
  3. data/.gitignore +22 -0
  4. data/LICENSE +47 -0
  5. data/README.rdoc +17 -0
  6. data/Rakefile +28 -0
  7. data/VERSION +1 -0
  8. data/extlib.gemspec +147 -0
  9. data/lib/extlib.rb +50 -0
  10. data/lib/extlib/array.rb +38 -0
  11. data/lib/extlib/assertions.rb +8 -0
  12. data/lib/extlib/blank.rb +89 -0
  13. data/lib/extlib/boolean.rb +11 -0
  14. data/lib/extlib/byte_array.rb +6 -0
  15. data/lib/extlib/class.rb +179 -0
  16. data/lib/extlib/datetime.rb +29 -0
  17. data/lib/extlib/dictionary.rb +433 -0
  18. data/lib/extlib/hash.rb +450 -0
  19. data/lib/extlib/hook.rb +407 -0
  20. data/lib/extlib/inflection.rb +442 -0
  21. data/lib/extlib/lazy_array.rb +453 -0
  22. data/lib/extlib/lazy_module.rb +18 -0
  23. data/lib/extlib/logger.rb +198 -0
  24. data/lib/extlib/mash.rb +157 -0
  25. data/lib/extlib/module.rb +51 -0
  26. data/lib/extlib/nil.rb +5 -0
  27. data/lib/extlib/numeric.rb +5 -0
  28. data/lib/extlib/object.rb +178 -0
  29. data/lib/extlib/object_space.rb +13 -0
  30. data/lib/extlib/pathname.rb +20 -0
  31. data/lib/extlib/pooling.rb +235 -0
  32. data/lib/extlib/rubygems.rb +38 -0
  33. data/lib/extlib/simple_set.rb +66 -0
  34. data/lib/extlib/string.rb +176 -0
  35. data/lib/extlib/struct.rb +17 -0
  36. data/lib/extlib/symbol.rb +21 -0
  37. data/lib/extlib/time.rb +44 -0
  38. data/lib/extlib/try_dup.rb +44 -0
  39. data/lib/extlib/virtual_file.rb +10 -0
  40. data/spec/array_spec.rb +40 -0
  41. data/spec/blank_spec.rb +86 -0
  42. data/spec/byte_array_spec.rb +8 -0
  43. data/spec/class_spec.rb +158 -0
  44. data/spec/datetime_spec.rb +22 -0
  45. data/spec/hash_spec.rb +536 -0
  46. data/spec/hook_spec.rb +1235 -0
  47. data/spec/inflection/plural_spec.rb +565 -0
  48. data/spec/inflection/singular_spec.rb +498 -0
  49. data/spec/inflection_extras_spec.rb +111 -0
  50. data/spec/lazy_array_spec.rb +1961 -0
  51. data/spec/lazy_module_spec.rb +38 -0
  52. data/spec/mash_spec.rb +312 -0
  53. data/spec/module_spec.rb +71 -0
  54. data/spec/object_space_spec.rb +10 -0
  55. data/spec/object_spec.rb +114 -0
  56. data/spec/pooling_spec.rb +511 -0
  57. data/spec/rcov.opts +6 -0
  58. data/spec/simple_set_spec.rb +58 -0
  59. data/spec/spec.opts +4 -0
  60. data/spec/spec_helper.rb +7 -0
  61. data/spec/string_spec.rb +222 -0
  62. data/spec/struct_spec.rb +13 -0
  63. data/spec/symbol_spec.rb +9 -0
  64. data/spec/time_spec.rb +31 -0
  65. data/spec/try_call_spec.rb +74 -0
  66. data/spec/try_dup_spec.rb +46 -0
  67. data/spec/virtual_file_spec.rb +22 -0
  68. data/tasks/ci.rake +1 -0
  69. data/tasks/metrics.rake +36 -0
  70. data/tasks/spec.rake +25 -0
  71. data/tasks/yard.rake +9 -0
  72. data/tasks/yardstick.rake +19 -0
  73. metadata +198 -0
@@ -0,0 +1,38 @@
1
+ require 'spec_helper'
2
+ require 'extlib/lazy_module'
3
+
4
+ describe LazyModule do
5
+ describe "instantiated with a block" do
6
+ it "defers block body evaluation" do
7
+ lambda do
8
+ LazyModule.new do
9
+ raise "Will only be evaluated when mixed in"
10
+ end
11
+ end.should_not raise_error
12
+ end
13
+ end
14
+
15
+
16
+ describe "included into hosting class" do
17
+ before :all do
18
+ KlazzyLazyModule = LazyModule.new do
19
+ def self.klassy
20
+ "Klazz"
21
+ end
22
+
23
+ def instancy
24
+ "Instanzz"
25
+ end
26
+ end
27
+
28
+ @klass = Class.new do
29
+ include KlazzyLazyModule
30
+ end
31
+ end
32
+
33
+ it "class evals block body" do
34
+ @klass.klassy.should == "Klazz"
35
+ @klass.new.instancy.should == "Instanzz"
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,312 @@
1
+ require 'spec_helper'
2
+ require 'extlib/mash'
3
+
4
+ class AwesomeHash < Hash
5
+ end
6
+
7
+ describe Mash do
8
+ before(:each) do
9
+ @hash = { "mash" => "indifferent", :hash => "different" }
10
+ @sub = AwesomeHash.new("mash" => "indifferent", :hash => "different")
11
+ end
12
+
13
+ describe "#initialize" do
14
+ it 'converts all keys into strings when param is a Hash' do
15
+ mash = Mash.new(@hash)
16
+
17
+ mash.keys.any? { |key| key.is_a?(Symbol) }.should be_false
18
+ end
19
+
20
+ it 'converts all pure Hash values into Mashes if param is a Hash' do
21
+ mash = Mash.new :hash => @hash
22
+
23
+ mash["hash"].should be_an_instance_of(Mash)
24
+ # sanity check
25
+ mash["hash"]["hash"].should == "different"
26
+ end
27
+
28
+ it 'doesn not convert Hash subclass values into Mashes' do
29
+ mash = Mash.new :sub => @sub
30
+ mash["sub"].should be_an_instance_of(AwesomeHash)
31
+ end
32
+
33
+ it 'converts all value items if value is an Array' do
34
+ mash = Mash.new :arry => { :hash => [@hash] }
35
+
36
+ mash["arry"].should be_an_instance_of(Mash)
37
+ # sanity check
38
+ mash["arry"]["hash"].first["hash"].should == "different"
39
+
40
+ end
41
+
42
+ it 'delegates to superclass constructor if param is not a Hash' do
43
+ mash = Mash.new("dash berlin")
44
+
45
+ mash["unexisting key"].should == "dash berlin"
46
+ end
47
+ end # describe "#initialize"
48
+
49
+
50
+
51
+ describe "#update" do
52
+ it 'converts all keys into strings when param is a Hash' do
53
+ mash = Mash.new(@hash)
54
+ mash.update("starry" => "night")
55
+
56
+ mash.keys.any? { |key| key.is_a?(Symbol) }.should be_false
57
+ end
58
+
59
+ it 'converts all Hash values into Mashes if param is a Hash' do
60
+ mash = Mash.new :hash => @hash
61
+ mash.update(:hash => { :hash => "is buggy in Ruby 1.8.6" })
62
+
63
+ mash["hash"].should be_an_instance_of(Mash)
64
+ end
65
+ end # describe "#update"
66
+
67
+
68
+
69
+ describe "#[]=" do
70
+ it 'converts key into string' do
71
+ mash = Mash.new(@hash)
72
+ mash[:hash] = { "starry" => "night" }
73
+
74
+ mash.keys.any? { |key| key.is_a?(Symbol) }.should be_false
75
+ end
76
+
77
+ it 'converts all Hash value into Mash' do
78
+ mash = Mash.new :hash => @hash
79
+ mash[:hash] = { :hash => "is buggy in Ruby 1.8.6" }
80
+
81
+ mash["hash"].should be_an_instance_of(Mash)
82
+ end
83
+ end # describe "#[]="
84
+
85
+
86
+
87
+ describe "#key?" do
88
+ before(:each) do
89
+ @mash = Mash.new(@hash)
90
+ end
91
+
92
+ it 'converts key before lookup' do
93
+ @mash.key?("mash").should be_true
94
+ @mash.key?(:mash).should be_true
95
+
96
+ @mash.key?("hash").should be_true
97
+ @mash.key?(:hash).should be_true
98
+
99
+ @mash.key?(:rainclouds).should be_false
100
+ @mash.key?("rainclouds").should be_false
101
+ end
102
+
103
+ it 'is aliased as include?' do
104
+ @mash.include?("mash").should be_true
105
+ @mash.include?(:mash).should be_true
106
+
107
+ @mash.include?("hash").should be_true
108
+ @mash.include?(:hash).should be_true
109
+
110
+ @mash.include?(:rainclouds).should be_false
111
+ @mash.include?("rainclouds").should be_false
112
+ end
113
+
114
+ it 'is aliased as member?' do
115
+ @mash.member?("mash").should be_true
116
+ @mash.member?(:mash).should be_true
117
+
118
+ @mash.member?("hash").should be_true
119
+ @mash.member?(:hash).should be_true
120
+
121
+ @mash.member?(:rainclouds).should be_false
122
+ @mash.member?("rainclouds").should be_false
123
+ end
124
+ end # describe "#key?"
125
+
126
+
127
+ describe "#dup" do
128
+ it 'returns instance of Mash' do
129
+ Mash.new(@hash).dup.should be_an_instance_of(Mash)
130
+ end
131
+
132
+ it 'preserves keys' do
133
+ mash = Mash.new(@hash)
134
+ dup = mash.dup
135
+
136
+ mash.keys.sort.should == dup.keys.sort
137
+ end
138
+
139
+ it 'preserves value' do
140
+ mash = Mash.new(@hash)
141
+ dup = mash.dup
142
+
143
+ mash.values.sort.should == dup.values.sort
144
+ end
145
+ end
146
+
147
+
148
+
149
+ describe "#to_hash" do
150
+ it 'returns instance of Mash' do
151
+ Mash.new(@hash).to_hash.should be_an_instance_of(Hash)
152
+ end
153
+
154
+ it 'preserves keys' do
155
+ mash = Mash.new(@hash)
156
+ converted = mash.to_hash
157
+
158
+ mash.keys.sort.should == converted.keys.sort
159
+ end
160
+
161
+ it 'preserves value' do
162
+ mash = Mash.new(@hash)
163
+ converted = mash.to_hash
164
+
165
+ mash.values.sort.should == converted.values.sort
166
+ end
167
+ end
168
+
169
+
170
+
171
+ describe "#symbolize_keys" do
172
+ it 'returns instance of Mash' do
173
+ Mash.new(@hash).symbolize_keys.should be_an_instance_of(Hash)
174
+ end
175
+
176
+ it 'converts keys to symbols' do
177
+ mash = Mash.new(@hash)
178
+ converted = mash.symbolize_keys
179
+
180
+ converted_keys = converted.keys.sort{|k1, k2| k1.to_s <=> k2.to_s}
181
+ orig_keys = mash.keys.map{|k| k.to_sym}.sort{|i1, i2| i1.to_s <=> i2.to_s}
182
+
183
+ converted_keys.should == orig_keys
184
+ end
185
+
186
+ it 'preserves value' do
187
+ mash = Mash.new(@hash)
188
+ converted = mash.symbolize_keys
189
+
190
+ mash.values.sort.should == converted.values.sort
191
+ end
192
+ end
193
+
194
+
195
+
196
+ describe "#delete" do
197
+ it 'converts Symbol key into String before deleting' do
198
+ mash = Mash.new(@hash)
199
+
200
+ mash.delete(:hash)
201
+ mash.key?("hash").should be_false
202
+ end
203
+
204
+ it 'works with String keys as well' do
205
+ mash = Mash.new(@hash)
206
+
207
+ mash.delete("mash")
208
+ mash.key?("mash").should be_false
209
+ end
210
+ end
211
+
212
+
213
+
214
+ describe "#except" do
215
+ it "converts Symbol key into String before calling super" do
216
+ mash = Mash.new(@hash)
217
+
218
+ hashless_mash = mash.except(:hash)
219
+ hashless_mash.key?("hash").should be_false
220
+ end
221
+
222
+ it "works with String keys as well" do
223
+ mash = Mash.new(@hash)
224
+
225
+ mashless_mash = mash.except("mash")
226
+ mashless_mash.key?("mash").should be_false
227
+ end
228
+
229
+ it "works with multiple keys" do
230
+ mash = Mash.new(@hash)
231
+
232
+ mashless = mash.except("hash", :mash)
233
+ mashless.key?(:hash).should be_false
234
+ mashless.key?("mash").should be_false
235
+ end
236
+
237
+ it "should return a mash" do
238
+ mash = Mash.new(@hash)
239
+
240
+ hashless_mash = mash.except(:hash)
241
+ hashless_mash.class.should be(Mash)
242
+ end
243
+ end
244
+
245
+
246
+
247
+ describe "#merge" do
248
+ before(:each) do
249
+ @mash = Mash.new(@hash).merge(:no => "in between")
250
+ end
251
+
252
+ it 'returns instance of Mash' do
253
+ @mash.should be_an_instance_of(Mash)
254
+ end
255
+
256
+ it 'merges in give Hash' do
257
+ @mash["no"].should == "in between"
258
+ end
259
+ end
260
+
261
+
262
+
263
+ describe "#fetch" do
264
+ before(:each) do
265
+ @mash = Mash.new(@hash).merge(:no => "in between")
266
+ end
267
+
268
+ it 'converts key before fetching' do
269
+ @mash.fetch("no").should == "in between"
270
+ end
271
+
272
+ it 'returns alternative value if key lookup fails' do
273
+ @mash.fetch("flying", "screwdriver").should == "screwdriver"
274
+ end
275
+ end
276
+
277
+
278
+ describe "#default" do
279
+ before(:each) do
280
+ @mash = Mash.new(:yet_another_technical_revolution)
281
+ end
282
+
283
+ it 'returns default value unless key exists in mash' do
284
+ @mash.default("peak oil is now behind, baby").should == :yet_another_technical_revolution
285
+ end
286
+
287
+ it 'returns existing value if key is Symbol and exists in mash' do
288
+ @mash.update(:no => "in between")
289
+ @mash.default(:no).should == "in between"
290
+ end
291
+ end
292
+
293
+
294
+ describe "#values_at" do
295
+ before(:each) do
296
+ @mash = Mash.new(@hash).merge(:no => "in between")
297
+ end
298
+
299
+ it 'is indifferent to whether keys are strings or symbols' do
300
+ @mash.values_at("hash", :mash, :no).should == ["different", "indifferent", "in between"]
301
+ end
302
+ end
303
+
304
+
305
+ describe "#stringify_keys!" do
306
+ it 'returns the mash itself' do
307
+ mash = Mash.new(@hash)
308
+
309
+ mash.stringify_keys!.object_id.should == mash.object_id
310
+ end
311
+ end
312
+ end
@@ -0,0 +1,71 @@
1
+ require 'spec_helper'
2
+ require 'extlib/module'
3
+
4
+ describe Module do
5
+
6
+ before(:all) do
7
+ module ::Foo
8
+ module ModBar
9
+ module Noo
10
+ module Too
11
+ module Boo
12
+ end
13
+ end
14
+ end
15
+ end
16
+
17
+ class Zed
18
+ end
19
+ end
20
+
21
+ class ::Baz
22
+ end
23
+
24
+ class ::Bar
25
+ end
26
+ end
27
+
28
+ it "should raise NameError for a missing constant" do
29
+ lambda { Foo.find_const('Moo') }.should raise_error(NameError)
30
+ lambda { Object.find_const('MissingConstant') }.should raise_error(NameError)
31
+ end
32
+
33
+ it "should be able to get a recursive constant" do
34
+ Object.find_const('Foo::ModBar').should == Foo::ModBar
35
+ end
36
+
37
+ it "should ignore get Constants from the Kernel namespace correctly" do
38
+ Object.find_const('::Foo::ModBar').should == ::Foo::ModBar
39
+ end
40
+
41
+ it "should find relative constants" do
42
+ Foo.find_const('ModBar').should == Foo::ModBar
43
+ Foo.find_const('Baz').should == Baz
44
+ end
45
+
46
+ it "should find sibling constants" do
47
+ Foo::ModBar.find_const("Zed").should == Foo::Zed
48
+ end
49
+
50
+ it "should find nested constants on nested constants" do
51
+ Foo::ModBar.find_const('Noo::Too').should == Foo::ModBar::Noo::Too
52
+ end
53
+
54
+ it "should find constants outside of nested constants" do
55
+ Foo::ModBar::Noo::Too.find_const("Zed").should == Foo::Zed
56
+ end
57
+
58
+ it 'should be able to find past the second nested level' do
59
+ Foo::ModBar::Noo.find_const('Too').should == Foo::ModBar::Noo::Too
60
+ Foo::ModBar::Noo::Too.find_const('Boo').should == Foo::ModBar::Noo::Too::Boo
61
+ end
62
+
63
+
64
+ it "should be able to deal with constants being added and removed" do
65
+ Object.find_const('Bar') # First we load Bar with find_const
66
+ Object.module_eval { remove_const('Bar') } # Now we delete it
67
+ module ::Bar; end; # Now we redefine it
68
+ Object.find_const('Bar').should == Bar
69
+ end
70
+
71
+ end
@@ -0,0 +1,10 @@
1
+ require 'spec_helper'
2
+ require 'extlib/object_space'
3
+
4
+ describe ObjectSpace, "#classes" do
5
+ it 'returns only classes, nothing else' do
6
+ ObjectSpace.classes.each do |klass|
7
+ Class.should === klass
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,114 @@
1
+ require 'spec_helper'
2
+ require 'extlib/object'
3
+
4
+ module HactiveSupport
5
+ class MemoizeConsideredUseless
6
+ end
7
+ end
8
+
9
+ class SymbolicDuck
10
+ def quack
11
+ end
12
+ end
13
+
14
+ class ClassyDuck
15
+ end
16
+
17
+ module Foo
18
+ class Bar
19
+ end
20
+ end
21
+
22
+ class Oi
23
+ attr_accessor :foo
24
+ end
25
+
26
+ describe Object do
27
+
28
+ describe "#full_const_get" do
29
+ it 'returns constant by FQ name in receiver namespace' do
30
+ Object.full_const_get("Oi").should == Oi
31
+ Object.full_const_get("Foo::Bar").should == Foo::Bar
32
+ end
33
+ end
34
+
35
+ describe "#full_const_set" do
36
+ it 'sets constant value by FQ name in receiver namespace' do
37
+ Object.full_const_set("HactiveSupport::MCU", HactiveSupport::MemoizeConsideredUseless)
38
+
39
+ Object.full_const_get("HactiveSupport::MCU").should == HactiveSupport::MemoizeConsideredUseless
40
+ HactiveSupport.full_const_get("MCU").should == HactiveSupport::MemoizeConsideredUseless
41
+ end
42
+ end
43
+
44
+ describe "#make_module" do
45
+ it 'creates a module from string FQ name' do
46
+ Object.make_module("Milano")
47
+ Object.make_module("Norway::Oslo")
48
+
49
+ Object.const_defined?("Milano").should == true
50
+ Norway.const_defined?("Oslo").should == true
51
+ end
52
+
53
+ it "handles the case where we already have a class in the heirarchy" do
54
+ Object.make_module("Foo::Bar::Baz")
55
+ Object.const_defined?("Foo").should == true
56
+ Foo.const_defined?("Bar").should == true
57
+ Foo::Bar.const_defined?("Baz").should == true
58
+ Foo::Bar::Baz.should be_kind_of(Module)
59
+ end
60
+ end
61
+
62
+
63
+ describe "#quacks_like?" do
64
+ it 'returns true if duck is a Symbol and receiver responds to it' do
65
+ SymbolicDuck.new.quacks_like?(:quack).should be_true
66
+ end
67
+
68
+ it 'returns false if duck is a Symbol and receiver DOES NOT respond to it' do
69
+ SymbolicDuck.new.quacks_like?(:wtf).should be_false
70
+ end
71
+
72
+ it 'returns true if duck is a class and receiver is its instance' do
73
+ receiver = ClassyDuck.new
74
+ receiver.quacks_like?(ClassyDuck).should be_true
75
+ end
76
+
77
+ it 'returns false if duck is a class and receiver IS NOT its instance' do
78
+ receiver = ClassyDuck.new
79
+ receiver.quacks_like?(SymbolicDuck).should be_false
80
+ end
81
+
82
+ it 'returns true if duck is an array and at least one of its members quacks like this duck' do
83
+ receiver = ClassyDuck.new
84
+ ary = [ClassyDuck, SymbolicDuck]
85
+
86
+ receiver.quacks_like?(ary).should be_true
87
+ end
88
+
89
+ it 'returns false if duck is an array and none of its members quacks like this duck' do
90
+ receiver = ClassyDuck.new
91
+ ary = [SymbolicDuck.new, SymbolicDuck]
92
+
93
+ receiver.quacks_like?(ary).should be_false
94
+ end
95
+ end
96
+
97
+ describe "#in?" do
98
+ it 'returns true if object is included in collection' do
99
+ @ary = [1, 2, 3]
100
+ @set = Set.new([2, 3, 5])
101
+
102
+ 1.in?(@ary).should be_true
103
+ 2.in?(@ary).should be_true
104
+ 3.in?(@ary).should be_true
105
+ 4.in?(@ary).should be_false
106
+
107
+ 1.in?(@set).should be_false
108
+ 2.in?(@set).should be_true
109
+ 3.in?(@set).should be_true
110
+ 4.in?(@set).should be_false
111
+ 5.in?(@set).should be_true
112
+ end
113
+ end
114
+ end