dm-core 1.1.0.rc2 → 1.1.0.rc3

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 (71) hide show
  1. data/Gemfile +1 -8
  2. data/VERSION +1 -1
  3. data/dm-core.gemspec +24 -15
  4. data/lib/dm-core.rb +9 -48
  5. data/lib/dm-core/adapters.rb +1 -1
  6. data/lib/dm-core/adapters/abstract_adapter.rb +2 -1
  7. data/lib/dm-core/associations/many_to_many.rb +3 -3
  8. data/lib/dm-core/associations/many_to_one.rb +15 -4
  9. data/lib/dm-core/associations/one_to_many.rb +1 -1
  10. data/lib/dm-core/associations/relationship.rb +7 -6
  11. data/lib/dm-core/collection.rb +7 -2
  12. data/lib/dm-core/core_ext/pathname.rb +0 -14
  13. data/lib/dm-core/ext/array.rb +41 -0
  14. data/lib/dm-core/ext/blank.rb +24 -0
  15. data/lib/dm-core/ext/hash.rb +67 -0
  16. data/lib/dm-core/ext/module.rb +49 -0
  17. data/lib/dm-core/ext/object.rb +57 -0
  18. data/lib/dm-core/ext/singleton_class.rb +8 -0
  19. data/lib/dm-core/ext/string.rb +24 -0
  20. data/lib/dm-core/ext/try_dup.rb +12 -0
  21. data/lib/dm-core/model.rb +2 -1
  22. data/lib/dm-core/model/property.rb +3 -2
  23. data/lib/dm-core/property.rb +1 -1
  24. data/lib/dm-core/property/class.rb +1 -1
  25. data/lib/dm-core/property/date.rb +3 -3
  26. data/lib/dm-core/property/date_time.rb +3 -3
  27. data/lib/dm-core/property/time.rb +3 -3
  28. data/lib/dm-core/property/typecast/time.rb +2 -2
  29. data/lib/dm-core/property_set.rb +1 -1
  30. data/lib/dm-core/query.rb +9 -12
  31. data/lib/dm-core/resource.rb +2 -2
  32. data/lib/dm-core/spec/lib/counter_adapter.rb +1 -1
  33. data/lib/dm-core/spec/lib/spec_helper.rb +1 -1
  34. data/lib/dm-core/spec/shared/resource_spec.rb +2 -1
  35. data/lib/dm-core/support/equalizer.rb +1 -1
  36. data/lib/dm-core/support/hook.rb +0 -15
  37. data/lib/dm-core/support/inflections.rb +60 -0
  38. data/lib/dm-core/support/inflector.rb +3 -0
  39. data/lib/dm-core/support/inflector/inflections.rb +211 -0
  40. data/lib/dm-core/support/inflector/methods.rb +151 -0
  41. data/lib/dm-core/support/lazy_array.rb +4 -4
  42. data/lib/dm-core/support/mash.rb +176 -0
  43. data/lib/dm-core/support/subject.rb +1 -1
  44. data/lib/dm-core/version.rb +1 -1
  45. data/spec/public/model/relationship_spec.rb +2 -1
  46. data/spec/public/shared/collection_shared_spec.rb +5 -2
  47. data/spec/public/shared/finder_shared_spec.rb +10 -6
  48. data/spec/semipublic/adapters/in_memory_adapter_spec.rb +1 -1
  49. data/spec/semipublic/query_spec.rb +2 -2
  50. data/spec/semipublic/resource/state/immutable_spec.rb +2 -1
  51. data/spec/semipublic/resource/state_spec.rb +1 -3
  52. data/spec/semipublic/shared/resource_state_shared_spec.rb +2 -1
  53. data/spec/semipublic/shared/subject_shared_spec.rb +1 -1
  54. data/spec/support/core_ext/hash.rb +10 -0
  55. data/spec/support/core_ext/inheritable_attributes.rb +46 -0
  56. data/spec/unit/array_spec.rb +8 -20
  57. data/spec/unit/blank_spec.rb +62 -0
  58. data/spec/unit/data_mapper/ordered_set/hash_spec.rb +1 -1
  59. data/spec/unit/hash_spec.rb +8 -16
  60. data/spec/unit/lazy_array_spec.rb +3 -14
  61. data/spec/unit/mash_spec.rb +312 -0
  62. data/spec/unit/module_spec.rb +15 -15
  63. data/spec/unit/object_spec.rb +9 -9
  64. data/spec/unit/try_dup_spec.rb +8 -8
  65. metadata +32 -39
  66. data/lib/dm-core/core_ext/array.rb +0 -36
  67. data/lib/dm-core/core_ext/hash.rb +0 -30
  68. data/lib/dm-core/core_ext/module.rb +0 -46
  69. data/lib/dm-core/core_ext/object.rb +0 -31
  70. data/lib/dm-core/core_ext/string.rb +0 -22
  71. data/lib/dm-core/core_ext/try_dup.rb +0 -44
@@ -0,0 +1,62 @@
1
+ require 'spec_helper'
2
+ require 'dm-core/ext/blank'
3
+
4
+ describe 'DataMapper::Ext.blank?', Object do
5
+ it 'should be blank if it is nil' do
6
+ object = Object.new
7
+ class << object
8
+ def nil?; true end
9
+ end
10
+ DataMapper::Ext.blank?(object).should == true
11
+ end
12
+
13
+ it 'should be blank if it is empty' do
14
+ DataMapper::Ext.blank?({}).should == true
15
+ DataMapper::Ext.blank?([]).should == true
16
+ end
17
+
18
+ it 'should not be blank if not nil or empty' do
19
+ DataMapper::Ext.blank?(Object.new).should == false
20
+ DataMapper::Ext.blank?([nil]).should == false
21
+ DataMapper::Ext.blank?({ nil => 0 }).should == false
22
+ end
23
+ end
24
+
25
+ describe 'DataMapper::Ext.blank?', Numeric do
26
+ it 'should never be blank' do
27
+ DataMapper::Ext.blank?(1).should == false
28
+ end
29
+ end
30
+
31
+ describe 'DataMapper::Ext.blank?', NilClass do
32
+ it 'should always be blank' do
33
+ DataMapper::Ext.blank?(nil).should == true
34
+ end
35
+ end
36
+
37
+ describe 'DataMapper::Ext.blank?', TrueClass do
38
+ it 'should never be blank' do
39
+ DataMapper::Ext.blank?(true).should == false
40
+ end
41
+ end
42
+
43
+ describe 'DataMapper::Ext.blank?', FalseClass do
44
+ it 'should always be blank' do
45
+ DataMapper::Ext.blank?(false).should == true
46
+ end
47
+ end
48
+
49
+ describe 'DataMapper::Ext.blank?', String do
50
+ it 'should be blank if empty' do
51
+ DataMapper::Ext.blank?('').should == true
52
+ end
53
+
54
+ it 'should be blank if it only contains whitespace' do
55
+ DataMapper::Ext.blank?(' ').should == true
56
+ DataMapper::Ext.blank?(" \r \n \t ").should == true
57
+ end
58
+
59
+ it 'should not be blank if it contains non-whitespace' do
60
+ DataMapper::Ext.blank?(' a ').should == false
61
+ end
62
+ end
@@ -8,5 +8,5 @@ describe 'DataMapper::OrderedSet#hash' do
8
8
  let(:ordered_set) { DataMapper::OrderedSet.new([ entry ]) }
9
9
 
10
10
  it { should be_kind_of(Integer) }
11
- it { should == ordered_set.entries.hash }
11
+ it { should == ordered_set.class.hash ^ ordered_set.entries.hash }
12
12
  end
@@ -1,25 +1,17 @@
1
1
  require 'spec_helper'
2
- require 'dm-core/core_ext/hash'
2
+ require 'dm-core/ext/hash'
3
+ require 'dm-core/support/mash'
3
4
 
4
- begin
5
- require 'active_support/hash_with_indifferent_access'
6
- unless defined?(Mash)
7
- Mash = ActiveSupport::HashWithIndifferentAccess
8
- end
9
- rescue LoadError
10
- require 'extlib/mash'
11
- end
12
-
13
- describe Hash, "only" do
5
+ describe DataMapper::Ext::Hash, "only" do
14
6
  before do
15
7
  @hash = { :one => 'ONE', 'two' => 'TWO', 3 => 'THREE', 4 => nil }
16
8
  end
17
9
 
18
10
  it "should return a hash with only the given key(s)" do
19
- @hash.only(:not_in_there).should == {}
20
- @hash.only(4).should == {4 => nil}
21
- @hash.only(:one).should == { :one => 'ONE' }
22
- @hash.only(:one, 3).should == { :one => 'ONE', 3 => 'THREE' }
11
+ DataMapper::Ext::Hash.only(@hash, :not_in_there).should == {}
12
+ DataMapper::Ext::Hash.only(@hash, 4).should == {4 => nil}
13
+ DataMapper::Ext::Hash.only(@hash, :one).should == { :one => 'ONE' }
14
+ DataMapper::Ext::Hash.only(@hash, :one, 3).should == { :one => 'ONE', 3 => 'THREE' }
23
15
  end
24
16
  end
25
17
 
@@ -30,7 +22,7 @@ describe Hash, 'to_mash' do
30
22
  end
31
23
 
32
24
  it "copies default Hash value to Mash" do
33
- @mash = @hash.to_mash
25
+ @mash = DataMapper::Ext::Hash.to_mash(@hash)
34
26
  @mash[:merb].should == 10
35
27
  end
36
28
  end
@@ -6,15 +6,15 @@ require 'dm-core/support/lazy_array'
6
6
  module LazyArraySpec
7
7
  module GroupMethods
8
8
  def self.extended(base)
9
- base.class_inheritable_accessor :loaded, :subject_block, :action_block
9
+ base.class_inheritable_accessor :loaded
10
10
  end
11
11
 
12
12
  def subject(&block)
13
- self.subject_block = block
13
+ let(:subject, &block)
14
14
  end
15
15
 
16
16
  def action(&block)
17
- self.action_block = block
17
+ let(:action, &block)
18
18
  end
19
19
 
20
20
  def should_respond_to(method)
@@ -111,22 +111,11 @@ module LazyArraySpec
111
111
  end
112
112
  end
113
113
  end
114
-
115
- module Methods
116
- def subject
117
- @subject ||= instance_eval(&self.class.subject_block)
118
- end
119
-
120
- def action
121
- instance_eval(&self.class.action_block)
122
- end
123
- end
124
114
  end
125
115
 
126
116
  [ false, true ].each do |loaded|
127
117
  describe LazyArray do
128
118
  extend LazyArraySpec::GroupMethods
129
- include LazyArraySpec::Methods
130
119
 
131
120
  self.loaded = loaded
132
121
 
@@ -0,0 +1,312 @@
1
+ require 'spec_helper'
2
+ require 'dm-core/support/mash'
3
+
4
+ class AwesomeHash < Hash
5
+ end
6
+
7
+ describe DataMapper::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 = DataMapper::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 = DataMapper::Mash.new :hash => @hash
22
+
23
+ mash["hash"].should be_an_instance_of(DataMapper::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 = DataMapper::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 = DataMapper::Mash.new :arry => { :hash => [@hash] }
35
+
36
+ mash["arry"].should be_an_instance_of(DataMapper::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 = DataMapper::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 = DataMapper::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 = DataMapper::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(DataMapper::Mash)
64
+ end
65
+ end # describe "#update"
66
+
67
+
68
+
69
+ describe "#[]=" do
70
+ it 'converts key into string' do
71
+ mash = DataMapper::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 = DataMapper::Mash.new :hash => @hash
79
+ mash[:hash] = { :hash => "is buggy in Ruby 1.8.6" }
80
+
81
+ mash["hash"].should be_an_instance_of(DataMapper::Mash)
82
+ end
83
+ end # describe "#[]="
84
+
85
+
86
+
87
+ describe "#key?" do
88
+ before(:each) do
89
+ @mash = DataMapper::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
+ DataMapper::Mash.new(@hash).dup.should be_an_instance_of(DataMapper::Mash)
130
+ end
131
+
132
+ it 'preserves keys' do
133
+ mash = DataMapper::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 = DataMapper::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
+ DataMapper::Mash.new(@hash).to_hash.should be_an_instance_of(Hash)
152
+ end
153
+
154
+ it 'preserves keys' do
155
+ mash = DataMapper::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 = DataMapper::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
+ DataMapper::Mash.new(@hash).symbolize_keys.should be_an_instance_of(Hash)
174
+ end
175
+
176
+ it 'converts keys to symbols' do
177
+ mash = DataMapper::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 = DataMapper::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 = DataMapper::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 = DataMapper::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 = DataMapper::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 = DataMapper::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 = DataMapper::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 = DataMapper::Mash.new(@hash)
239
+
240
+ hashless_mash = mash.except(:hash)
241
+ hashless_mash.class.should be(DataMapper::Mash)
242
+ end
243
+ end
244
+
245
+
246
+
247
+ describe "#merge" do
248
+ before(:each) do
249
+ @mash = DataMapper::Mash.new(@hash).merge(:no => "in between")
250
+ end
251
+
252
+ it 'returns instance of Mash' do
253
+ @mash.should be_an_instance_of(DataMapper::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 = DataMapper::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 = DataMapper::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 = DataMapper::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 = DataMapper::Mash.new(@hash)
308
+
309
+ mash.stringify_keys!.object_id.should == mash.object_id
310
+ end
311
+ end
312
+ end