gorillib 0.0.8 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. data/CHANGELOG.textile +6 -0
  2. data/README.textile +34 -11
  3. data/VERSION +1 -1
  4. data/gorillib.gemspec +63 -5
  5. data/lib/gorillib/enumerable/sum.rb +2 -2
  6. data/lib/gorillib/hash/compact.rb +2 -29
  7. data/lib/gorillib/hash/deep_compact.rb +2 -12
  8. data/lib/gorillib/hash/deep_dup.rb +4 -0
  9. data/lib/gorillib/hash/deep_merge.rb +2 -14
  10. data/lib/gorillib/hash/indifferent_access.rb +207 -0
  11. data/lib/gorillib/hash/keys.rb +2 -40
  12. data/lib/gorillib/hash/reverse_merge.rb +2 -24
  13. data/lib/gorillib/hash/slice.rb +2 -51
  14. data/lib/gorillib/hash/tree_merge.rb +4 -0
  15. data/lib/gorillib/hashlike.rb +824 -0
  16. data/lib/gorillib/hashlike/compact.rb +60 -0
  17. data/lib/gorillib/hashlike/deep_compact.rb +18 -0
  18. data/lib/gorillib/hashlike/deep_dup.rb +15 -0
  19. data/lib/gorillib/hashlike/deep_merge.rb +20 -0
  20. data/lib/gorillib/hashlike/hashlike_via_accessors.rb +169 -0
  21. data/lib/gorillib/hashlike/keys.rb +59 -0
  22. data/lib/gorillib/hashlike/reverse_merge.rb +31 -0
  23. data/lib/gorillib/hashlike/slice.rb +67 -0
  24. data/lib/gorillib/hashlike/tree_merge.rb +76 -0
  25. data/lib/gorillib/metaprogramming/mattr_accessor.rb +1 -1
  26. data/lib/gorillib/receiver.rb +315 -0
  27. data/lib/gorillib/receiver/active_model_shim.rb +19 -0
  28. data/lib/gorillib/receiver/acts_as_hash.rb +191 -0
  29. data/lib/gorillib/receiver/acts_as_loadable.rb +42 -0
  30. data/lib/gorillib/receiver/tree_diff.rb +74 -0
  31. data/lib/gorillib/receiver/validations.rb +30 -0
  32. data/lib/gorillib/struct/acts_as_hash.rb +108 -0
  33. data/lib/gorillib/struct/hashlike_iteration.rb +0 -0
  34. data/notes/fancy_hashes_and_receivers.textile +120 -0
  35. data/notes/hash_rdocs.textile +97 -0
  36. data/spec/hash/deep_merge_spec.rb +0 -2
  37. data/spec/hash/indifferent_access_spec.rb +391 -0
  38. data/spec/hash/slice_spec.rb +35 -12
  39. data/spec/hashlike/behave_same_as_hash_spec.rb +105 -0
  40. data/spec/hashlike/hashlike_behavior_spec.rb +824 -0
  41. data/spec/hashlike/hashlike_via_accessors_fuzzing_spec.rb +37 -0
  42. data/spec/hashlike/hashlike_via_accessors_spec.rb +262 -0
  43. data/spec/hashlike_spec.rb +302 -0
  44. data/spec/metaprogramming/aliasing_spec.rb +3 -0
  45. data/spec/metaprogramming/cattr_accessor_spec.rb +2 -0
  46. data/spec/metaprogramming/class_attribute_spec.rb +2 -0
  47. data/spec/metaprogramming/delegation_spec.rb +2 -0
  48. data/spec/metaprogramming/mattr_accessor_spec.rb +2 -0
  49. data/spec/metaprogramming/singleton_class_spec.rb +3 -0
  50. data/spec/receiver/acts_as_hash_spec.rb +286 -0
  51. data/spec/receiver_spec.rb +478 -0
  52. data/spec/spec_helper.rb +11 -6
  53. data/spec/string/truncate_spec.rb +1 -0
  54. data/spec/struct/acts_as_hash_fuzz_spec.rb +67 -0
  55. data/spec/struct/acts_as_hash_spec.rb +426 -0
  56. data/spec/support/hashlike_fuzzing_helper.rb +127 -0
  57. data/spec/support/hashlike_helper.rb +75 -0
  58. data/spec/support/hashlike_struct_helper.rb +37 -0
  59. data/spec/support/hashlike_via_delegation.rb +30 -0
  60. data/spec/support/matchers/be_array_eql.rb +12 -0
  61. data/spec/support/matchers/be_hash_eql.rb +14 -0
  62. data/spec/support/matchers/enumerate_method.rb +10 -0
  63. data/spec/support/matchers/evaluate_to_true.rb +5 -0
  64. metadata +62 -4
@@ -0,0 +1,37 @@
1
+ # require File.dirname(__FILE__)+'/../spec_helper'
2
+ # require GORILLIB_ROOT_DIR('spec/support/hashlike_fuzzing_helper')
3
+ # require 'gorillib/hashlike'
4
+ # require 'gorillib/hashlike/hashlike_via_accessors'
5
+ #
6
+ # class UsingHashlikeViaAccessors
7
+ # include Gorillib::Hashlike::HashlikeViaAccessors
8
+ # include Gorillib::Hashlike
9
+ #
10
+ # attr_accessor :a, :b, :c, :nil_val, :false_val, :z
11
+ #
12
+ # # We override these just to be able to compare exceptions.
13
+ # def to_s()
14
+ # '{' + [:a, :b, :c, :nil_val, :false_val, :z].map{|k| [k, self[k]].join('=>') }.join(',') + '}'
15
+ # end
16
+ # def ==(other_hash)
17
+ # (length == other_hash.length) && all?{|k,v| v == other_hash[k] }
18
+ # end
19
+ # end
20
+ #
21
+ #
22
+ # describe Gorillib::Hashlike::HashlikeViaAccessors do
23
+ # include HashlikeFuzzingHelper
24
+ #
25
+ #
26
+ # before do
27
+ # @total = 0
28
+ # hsh = { :a => 3, :b => 4, :c => nil, :nil_val => nil, :false_val => false, :z => nil }
29
+ # @hsh_symk = hsh.dup
30
+ # @hsh_strk = {} ; hsh.each{|k,v| @hsh_strk[k.to_s] = v }
31
+ # @hsh_wia = hsh.with_indifferent_access
32
+ # @hshlike = InternalHash.new.merge(hsh)
33
+ #
34
+ # p [@hshlike]
35
+ # end
36
+ #
37
+ # end
@@ -0,0 +1,262 @@
1
+ require File.dirname(__FILE__)+'/../spec_helper'
2
+ require 'gorillib/hashlike'
3
+ require 'gorillib/hashlike/hashlike_via_accessors'
4
+ require GORILLIB_ROOT_DIR('spec/support/hashlike_via_delegation')
5
+ require GORILLIB_ROOT_DIR('spec/support/hashlike_helper')
6
+ require GORILLIB_ROOT_DIR('spec/hashlike/hashlike_behavior_spec')
7
+
8
+ class SimpleHashlikeViaAccessors
9
+ attr_accessor :a, :b, :c, :nil_val, :false_val, :new_key
10
+ include Gorillib::Hashlike::HashlikeViaAccessors
11
+ include Gorillib::Hashlike
12
+ end
13
+
14
+ describe Gorillib::Hashlike::HashlikeViaAccessors do
15
+
16
+ before do
17
+ @hshlike = SimpleHashlikeViaAccessors.new.merge(HashlikeHelper::HASH_TO_TEST_HL_V_A.dup)
18
+ @empty_hshlike = SimpleHashlikeViaAccessors.new
19
+ @hshlike_with_array_vals = SimpleHashlikeViaAccessors.new.merge(HashlikeHelper::BASE_HSH_WITH_ARRAY_VALS.dup)
20
+ #
21
+ @hshlike_subklass = Class.new(SimpleHashlikeViaAccessors)
22
+ @hshlike_subklass_inst = @hshlike_subklass.new.merge(HashlikeHelper::BASE_HSH.dup)
23
+ end
24
+
25
+
26
+ # ===========================================================================
27
+ #
28
+ # Fundamental behavior
29
+
30
+ describe '#[] and #[]= and #store' do
31
+ it_should_behave_like :hashlike_store_and_retrieve
32
+ it_should_behave_like :references_string_and_symbol_keys_equivalently
33
+ it 'reject unknown keys' do
34
+ lambda{ @hshlike[:fnord] = 69 }.should raise_error NoMethodError, /undefined method `fnord=' for/
35
+ lambda{ @hshlike[:fnord] }.should raise_error NoMethodError, /undefined method `fnord' for/
36
+ @hshlike.delete(:fnord).should be_nil
37
+ end
38
+ it 'accepts defined but unset keys' do
39
+ @hshlike[:new_key].should be_nil
40
+ @hshlike[:new_key] = 69
41
+ @hshlike[:new_key].should == 69
42
+ end
43
+ it 'does not allow nil, Object, or other non-stringy keys' do
44
+ lambda{ @hshlike[300] = :i_haz_num }.should raise_error(ArgumentError, "Keys for SimpleHashlikeViaAccessors must be symbols, strings or respond to #to_sym")
45
+ lambda{ @hshlike[nil] = :i_haz_nil }.should raise_error(ArgumentError, "Keys for SimpleHashlikeViaAccessors must be symbols, strings or respond to #to_sym")
46
+ obj = Object.new
47
+ lambda{ @hshlike[obj] = :i_haz_obj }.should raise_error(ArgumentError, "Keys for SimpleHashlikeViaAccessors must be symbols, strings or respond to #to_sym")
48
+ def obj.to_sym() :c ; end
49
+ @hshlike[obj] = :i_haz_obj
50
+ @hshlike[obj].should == :i_haz_obj
51
+ end
52
+ end
53
+
54
+ describe '#delete' do
55
+ it_should_behave_like :hashlike_delete
56
+ end
57
+
58
+ describe '#keys' do
59
+ it_should_behave_like :hashlike_keys
60
+ end
61
+
62
+ # ===========================================================================
63
+ #
64
+ # Iteration
65
+
66
+ describe '#each_pair' do
67
+ describe 'with block' do
68
+ it_should_behave_like :each_pair_on_stringlike_keys, :each_pair
69
+ end
70
+ it_should_behave_like :with_no_block_returns_enumerator, :each_pair
71
+ end
72
+
73
+ describe '#each' do
74
+ describe 'with block' do
75
+ it_should_behave_like :each_pair_on_stringlike_keys, :each
76
+ end
77
+ it_should_behave_like :with_no_block_returns_enumerator, :each
78
+ end
79
+
80
+ describe '#each_key' do
81
+ describe 'with block' do
82
+ it_should_behave_like :each_key_on_stringlike_keys
83
+ end
84
+ it_should_behave_like :with_no_block_returns_enumerator, :each_key
85
+ end
86
+
87
+ describe '#each_value' do
88
+ describe 'with block' do
89
+ it_should_behave_like :each_value_on_stringlike_keys
90
+ end
91
+ it_should_behave_like :with_no_block_returns_enumerator, :each_value
92
+ end
93
+
94
+ # ===========================================================================
95
+ #
96
+ # Retrieval and Membership
97
+
98
+ describe '#values' do
99
+ it_should_behave_like :hashlike_values
100
+ end
101
+
102
+ describe '#values_at' do
103
+ it_should_behave_like :hashlike_values_at_or_of, :values_at
104
+ end
105
+
106
+ describe '#values_of' do
107
+ it_should_behave_like :hashlike_values_at_or_of, :values_of
108
+ end
109
+
110
+ describe '#length' do
111
+ it_should_behave_like :hashlike_length, :length
112
+ end
113
+
114
+ describe '#size' do
115
+ it_should_behave_like :hashlike_length, :size
116
+ end
117
+
118
+ describe '#has_key?' do
119
+ it_should_behave_like :hashlike_has_key?, :has_key?
120
+ it_should_behave_like :hashlike_has_key_string_and_symbol_equivalent, :has_key?
121
+ end
122
+
123
+ describe '#include?' do
124
+ it_should_behave_like :hashlike_has_key?, :include?
125
+ it_should_behave_like :hashlike_has_key_string_and_symbol_equivalent, :include?
126
+ end
127
+
128
+ describe '#key?' do
129
+ it_should_behave_like :hashlike_has_key?, :key?
130
+ it_should_behave_like :hashlike_has_key_string_and_symbol_equivalent, :key?
131
+ end
132
+
133
+ describe '#member?' do
134
+ it_should_behave_like :hashlike_has_key?, :member?
135
+ it_should_behave_like :hashlike_has_key_string_and_symbol_equivalent, :member?
136
+ end
137
+
138
+ describe '#has_value?' do
139
+ it_should_behave_like :hashlike_has_value?, :has_value?
140
+ end
141
+
142
+ describe '#value?' do
143
+ it_should_behave_like :hashlike_has_value?, :value?
144
+ end
145
+
146
+ describe '#fetch' do
147
+ it_should_behave_like :hashlike_fetch
148
+ end
149
+
150
+ describe '#key' do
151
+ it_should_behave_like :hashlike_key
152
+ end
153
+
154
+ describe '#assoc' do
155
+ it_should_behave_like :hashlike_assoc
156
+ end
157
+
158
+ describe '#rassoc' do
159
+ it_should_behave_like :hashlike_rassoc
160
+ end
161
+
162
+ describe '#empty?' do
163
+ it_should_behave_like :hashlike_empty?
164
+ end
165
+
166
+ # ===========================================================================
167
+ #
168
+ # Update, merge!, merge
169
+
170
+ describe 'update' do
171
+ it_should_behave_like :merging_method, :update
172
+ it_should_behave_like :merging_method_with_normal_keys, :update
173
+ it_should_behave_like :merging_method_inplace, :update
174
+ end
175
+
176
+ describe '#merge!' do
177
+ it_should_behave_like :merging_method, :merge!
178
+ it_should_behave_like :merging_method_with_normal_keys, :merge!
179
+ it_should_behave_like :merging_method_inplace, :merge!
180
+ end
181
+
182
+ describe '#merge' do
183
+ it_should_behave_like :merging_method, :merge
184
+ it_should_behave_like :merging_method_with_normal_keys, :merge
185
+ it_should_behave_like :merging_method_returning_new, :merge
186
+ end
187
+
188
+ # ===========================================================================
189
+ #
190
+ # Filters
191
+
192
+ describe '#reject!' do
193
+ it_should_behave_like :hashlike_filter, :reject!
194
+ it_should_behave_like :rejection_filter, :reject!
195
+ it_should_behave_like :filter_modifies_self_returns_nil_if_unchanged, :reject!, false
196
+ end
197
+
198
+ describe '#select!' do
199
+ it_should_behave_like :hashlike_filter, :select!
200
+ it_should_behave_like :selection_filter, :select!
201
+ it_should_behave_like :filter_modifies_self_returns_nil_if_unchanged, :select!, true
202
+ end
203
+
204
+ describe '#delete_if' do
205
+ it_should_behave_like :hashlike_filter, :delete_if
206
+ it_should_behave_like :rejection_filter, :delete_if
207
+ it_should_behave_like :filter_modifies_self_returns_self, :delete_if, false
208
+ end
209
+
210
+ describe '#keep_if' do
211
+ it_should_behave_like :hashlike_filter, :keep_if
212
+ it_should_behave_like :selection_filter, :keep_if
213
+ it_should_behave_like :filter_modifies_self_returns_self, :keep_if, true
214
+ end
215
+
216
+ describe '#reject' do
217
+ it_should_behave_like :hashlike_filter, :select
218
+ it_should_behave_like :selection_filter, :select
219
+ it_should_behave_like :filter_does_not_modify_self_returns_same_class, :reject, false
220
+ end
221
+
222
+ describe '#select' do
223
+ it_should_behave_like :hashlike_filter, :select
224
+ it_should_behave_like :selection_filter, :select
225
+ it_should_behave_like :filter_does_not_modify_self_returns_same_class, :select, true
226
+ end
227
+
228
+ describe '#clear' do
229
+ it_should_behave_like :hashlike_clear
230
+ end
231
+
232
+ # ===========================================================================
233
+ #
234
+ # Conversion
235
+
236
+ describe '#to_hash' do
237
+ it_should_behave_like :hashlike_to_hash
238
+ end
239
+
240
+ describe '#invert' do
241
+ it_should_behave_like :hashlike_invert
242
+ end
243
+
244
+ describe '#flatten' do
245
+ it_should_behave_like :hashlike_flatten
246
+ end
247
+
248
+ # ===========================================================================
249
+ #
250
+ # Sanity check
251
+
252
+ it 'built test objects correctly' do
253
+ @hshlike_subklass .should < @hshlike.class
254
+ @hshlike_subklass .should_not == @hshlike.class
255
+ @hshlike_subklass_inst .should be_a(SimpleHashlikeViaAccessors)
256
+ @hshlike_subklass_inst .should be_a(@hshlike_subklass)
257
+ @hshlike_subklass_inst .should_not be_an_instance_of(SimpleHashlikeViaAccessors)
258
+ @hshlike .should_not be_a(@hshlike_subklass)
259
+ @hshlike .should be_an_instance_of(SimpleHashlikeViaAccessors)
260
+ end
261
+
262
+ end
@@ -0,0 +1,302 @@
1
+ require File.expand_path(File.dirname(__FILE__)+'/spec_helper')
2
+ require 'gorillib/hashlike'
3
+ require GORILLIB_ROOT_DIR('spec/support/hashlike_via_delegation')
4
+ require GORILLIB_ROOT_DIR('spec/support/hashlike_helper')
5
+ require GORILLIB_ROOT_DIR('spec/hashlike/hashlike_behavior_spec')
6
+
7
+
8
+
9
+
10
+
11
+
12
+
13
+ describe Gorillib::Hashlike do
14
+
15
+ before do
16
+ @hshlike = InternalHash.new.merge(HashlikeHelper::BASE_HSH.dup)
17
+ @empty_hshlike = InternalHash.new
18
+ @hshlike_with_array_keys = InternalHash.new.merge(HashlikeHelper::BASE_HSH_WITH_ARRAY_KEYS.dup)
19
+ @hshlike_with_array_vals = InternalHash.new.merge(HashlikeHelper::BASE_HSH_WITH_ARRAY_VALS.dup)
20
+ #
21
+ @hshlike_subklass = Class.new(InternalHash)
22
+ @hshlike_subklass_inst = @hshlike_subklass.new.merge(HashlikeHelper::BASE_HSH.dup)
23
+ end
24
+
25
+ # ===========================================================================
26
+ #
27
+ # Fundamental behavior
28
+
29
+ describe '#[] and #[]= and #store' do
30
+ it_should_behave_like :hashlike_store_and_retrieve
31
+ it_should_behave_like :references_complex_keys
32
+ it_should_behave_like :accepts_arbitrary_keys
33
+ end
34
+
35
+ describe '#delete' do
36
+ it_should_behave_like :hashlike_delete
37
+ end
38
+
39
+ describe '#keys' do
40
+ it_should_behave_like :hashlike_keys
41
+ end
42
+
43
+ # ===========================================================================
44
+ #
45
+ # Iteration
46
+
47
+ describe '#each_pair' do
48
+ describe 'with block' do
49
+ it_should_behave_like :each_pair_on_stringlike_keys, :each_pair
50
+ it_should_behave_like :each_pair_on_complex_keys, :each_pair
51
+ end
52
+ it_should_behave_like :with_no_block_returns_enumerator, :each_pair
53
+ end
54
+
55
+ describe '#each' do
56
+ describe 'with block' do
57
+ it_should_behave_like :each_pair_on_stringlike_keys, :each
58
+ it_should_behave_like :each_pair_on_complex_keys, :each
59
+ end
60
+ it_should_behave_like :with_no_block_returns_enumerator, :each
61
+ end
62
+
63
+ describe '#each_key' do
64
+ describe 'with block' do
65
+ it_should_behave_like :each_key_on_stringlike_keys
66
+ it_should_behave_like :each_key_on_complex_keys
67
+ end
68
+ it_should_behave_like :with_no_block_returns_enumerator, :each_key
69
+ end
70
+
71
+ describe '#each_value' do
72
+ describe 'with block' do
73
+ it_should_behave_like :each_value_on_stringlike_keys
74
+ end
75
+ it_should_behave_like :with_no_block_returns_enumerator, :each_value
76
+ end
77
+
78
+ # ===========================================================================
79
+ #
80
+ # Retrieval and Membership
81
+
82
+ describe '#values' do
83
+ it_should_behave_like :hashlike_values
84
+ end
85
+
86
+ describe '#values_at' do
87
+ it_should_behave_like :hashlike_values_at_or_of, :values_at
88
+ end
89
+
90
+ describe '#values_of' do
91
+ it_should_behave_like :hashlike_values_at_or_of, :values_of
92
+ end
93
+
94
+ describe '#length' do
95
+ it_should_behave_like :hashlike_length, :length
96
+ end
97
+
98
+ describe '#size' do
99
+ it_should_behave_like :hashlike_length, :size
100
+ end
101
+
102
+ describe '#has_key?' do
103
+ it_should_behave_like :hashlike_has_key?, :has_key?
104
+ it_should_behave_like :hashlike_has_key_on_complex_keys, :has_key?
105
+ end
106
+
107
+ describe '#include?' do
108
+ it_should_behave_like :hashlike_has_key?, :include?
109
+ it_should_behave_like :hashlike_has_key_on_complex_keys, :include?
110
+ end
111
+
112
+ describe '#key?' do
113
+ it_should_behave_like :hashlike_has_key?, :key?
114
+ it_should_behave_like :hashlike_has_key_on_complex_keys, :key?
115
+ end
116
+
117
+ describe '#member?' do
118
+ it_should_behave_like :hashlike_has_key?, :member?
119
+ it_should_behave_like :hashlike_has_key_on_complex_keys, :member?
120
+ end
121
+
122
+ describe '#has_value?' do
123
+ it_should_behave_like :hashlike_has_value?, :has_value?
124
+ it_should_behave_like :hashlike_has_value_on_complex_keys, :has_value?
125
+ end
126
+
127
+ describe '#value?' do
128
+ it_should_behave_like :hashlike_has_value?, :value?
129
+ it_should_behave_like :hashlike_has_value_on_complex_keys, :value?
130
+ end
131
+
132
+ describe '#fetch' do
133
+ it_should_behave_like :hashlike_fetch
134
+ end
135
+
136
+ describe '#key' do
137
+ it_should_behave_like :hashlike_key
138
+ end
139
+
140
+ describe '#assoc' do
141
+ it_should_behave_like :hashlike_assoc
142
+ end
143
+
144
+ describe '#rassoc' do
145
+ it_should_behave_like :hashlike_rassoc
146
+ end
147
+
148
+ describe '#empty?' do
149
+ it_should_behave_like :hashlike_empty?
150
+ end
151
+
152
+ # ===========================================================================
153
+ #
154
+ # Update, merge!, merge
155
+
156
+ describe 'update' do
157
+ it_should_behave_like :merging_method, :update
158
+ it_should_behave_like :merging_method_with_normal_keys, :update
159
+ it_should_behave_like :merging_method_inplace, :update
160
+ end
161
+
162
+ describe '#merge!' do
163
+ it_should_behave_like :merging_method, :merge!
164
+ it_should_behave_like :merging_method_with_normal_keys, :merge!
165
+ it_should_behave_like :merging_method_inplace, :merge!
166
+ end
167
+
168
+ describe '#merge' do
169
+ it_should_behave_like :merging_method, :merge
170
+ it_should_behave_like :merging_method_with_normal_keys, :merge
171
+ it_should_behave_like :merging_method_returning_new, :merge
172
+ end
173
+
174
+ # ===========================================================================
175
+ #
176
+ # Filters
177
+
178
+ describe '#reject!' do
179
+ it_should_behave_like :hashlike_filter, :reject!
180
+ it_should_behave_like :rejection_filter, :reject!
181
+ it_should_behave_like :filter_modifies_self_returns_nil_if_unchanged, :reject!, false
182
+ end
183
+
184
+ describe '#select!' do
185
+ it_should_behave_like :hashlike_filter, :select!
186
+ it_should_behave_like :selection_filter, :select!
187
+ it_should_behave_like :filter_modifies_self_returns_nil_if_unchanged, :select!, true
188
+ end
189
+
190
+ describe '#delete_if' do
191
+ it_should_behave_like :hashlike_filter, :delete_if
192
+ it_should_behave_like :rejection_filter, :delete_if
193
+ it_should_behave_like :filter_modifies_self_returns_self, :delete_if, false
194
+ end
195
+
196
+ describe '#keep_if' do
197
+ it_should_behave_like :hashlike_filter, :keep_if
198
+ it_should_behave_like :selection_filter, :keep_if
199
+ it_should_behave_like :filter_modifies_self_returns_self, :keep_if, true
200
+ end
201
+
202
+ describe '#reject' do
203
+ it_should_behave_like :hashlike_filter, :select
204
+ it_should_behave_like :selection_filter, :select
205
+ it_should_behave_like :filter_does_not_modify_self_returns_same_class, :reject, false
206
+ end
207
+
208
+ describe '#select' do
209
+ it_should_behave_like :hashlike_filter, :select
210
+ it_should_behave_like :selection_filter, :select
211
+ it_should_behave_like :filter_does_not_modify_self_returns_same_class, :select, true
212
+ end
213
+
214
+ describe '#clear' do
215
+ it_should_behave_like :hashlike_clear
216
+ end
217
+
218
+ # ===========================================================================
219
+ #
220
+ # Conversion
221
+
222
+ describe '#to_hash' do
223
+ it_should_behave_like :hashlike_to_hash
224
+ end
225
+
226
+ describe '#invert' do
227
+ it_should_behave_like :hashlike_invert
228
+ end
229
+
230
+ describe '#flatten' do
231
+ it_should_behave_like :hashlike_flatten
232
+ end
233
+
234
+ # ===========================================================================
235
+ #
236
+ # Method Decoration
237
+
238
+ describe 'including Hashlike' do
239
+ module CollidesWithEnumerable ; def map() 3 ; end ; def keys(); [] ; end ; end
240
+ it 'includes enumerable by default' do
241
+ foo_class = Class.new(Object) do
242
+ include CollidesWithEnumerable
243
+ include Gorillib::Hashlike
244
+ end
245
+ #
246
+ foo_class.should include(Enumerable)
247
+ # Enumerable's map method won
248
+ foo_class.new.first.should be_nil
249
+ end
250
+ it 'does not include enumerable if already included' do
251
+ foo_class = Class.new(Object) do
252
+ include Enumerable
253
+ include CollidesWithEnumerable
254
+ include Gorillib::Hashlike
255
+ end
256
+ #
257
+ foo_class.should include(Enumerable)
258
+ # Enumerable wasn't reincluded, so CollidesWithEnumerable's 'map method won
259
+ foo_class.new.map.should == 3
260
+ end
261
+ it 'defines iterator by default' do
262
+ foo_class = Class.new(Object) do
263
+ include Gorillib::Hashlike
264
+ end
265
+ foo_class.should include(Gorillib::Hashlike::EnumerateFromKeys)
266
+ [:each, :each_pair, :length, :values, :values_at].each{|meth| foo_class.should be_method_defined(meth) }
267
+ end
268
+ it 'does not define iterators if #each_pair is already defined' do
269
+ foo_class = Class.new(Object) do
270
+ def each_pair() 3 ; end
271
+ def length() 3 ; end
272
+ include Gorillib::Hashlike
273
+ end
274
+ foo_class.should_not include(Gorillib::Hashlike::EnumerateFromKeys)
275
+ foo_class .should be_method_defined(:each_pair)
276
+ [:each, :values, :values_at].each{|meth| foo_class.should_not be_method_defined(meth) }
277
+ end
278
+ it 'does not implement the default, rehash, replace, compare_by or shift families of methods' do
279
+ ({}.methods.map(&:to_sym) -
280
+ (@hshlike.methods.map(&:to_sym) +
281
+ HashlikeHelper::OMITTED_METHODS_FROM_HASH +
282
+ HashlikeHelper::FANCY_HASHLIKE_METHODS
283
+ )
284
+ ).should == []
285
+ end
286
+ end # including Hashlike
287
+
288
+ # ===========================================================================
289
+ #
290
+ # Sanity check
291
+
292
+ it 'built test objects correctly' do
293
+ @hshlike_subklass .should < @hshlike.class
294
+ @hshlike_subklass .should_not == @hshlike.class
295
+ @hshlike_subklass_inst .should be_a(InternalHash)
296
+ @hshlike_subklass_inst .should be_a(@hshlike_subklass)
297
+ @hshlike_subklass_inst .should_not be_an_instance_of(InternalHash)
298
+ @hshlike .should_not be_a(@hshlike_subklass)
299
+ @hshlike .should be_an_instance_of(InternalHash)
300
+ end
301
+
302
+ end