mongo_mapper_ign 0.7.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (105) hide show
  1. data/.gitignore +10 -0
  2. data/LICENSE +20 -0
  3. data/README.rdoc +35 -0
  4. data/Rakefile +37 -0
  5. data/bin/mmconsole +60 -0
  6. data/lib/mongo_mapper.rb +116 -0
  7. data/lib/mongo_mapper/document.rb +313 -0
  8. data/lib/mongo_mapper/embedded_document.rb +70 -0
  9. data/lib/mongo_mapper/plugins.rb +35 -0
  10. data/lib/mongo_mapper/plugins/associations.rb +114 -0
  11. data/lib/mongo_mapper/plugins/associations/base.rb +123 -0
  12. data/lib/mongo_mapper/plugins/associations/belongs_to_polymorphic_proxy.rb +30 -0
  13. data/lib/mongo_mapper/plugins/associations/belongs_to_proxy.rb +25 -0
  14. data/lib/mongo_mapper/plugins/associations/collection.rb +21 -0
  15. data/lib/mongo_mapper/plugins/associations/embedded_collection.rb +39 -0
  16. data/lib/mongo_mapper/plugins/associations/in_array_proxy.rb +144 -0
  17. data/lib/mongo_mapper/plugins/associations/many_documents_as_proxy.rb +28 -0
  18. data/lib/mongo_mapper/plugins/associations/many_documents_proxy.rb +129 -0
  19. data/lib/mongo_mapper/plugins/associations/many_embedded_polymorphic_proxy.rb +31 -0
  20. data/lib/mongo_mapper/plugins/associations/many_embedded_proxy.rb +23 -0
  21. data/lib/mongo_mapper/plugins/associations/many_polymorphic_proxy.rb +13 -0
  22. data/lib/mongo_mapper/plugins/associations/one_embedded_proxy.rb +41 -0
  23. data/lib/mongo_mapper/plugins/associations/one_proxy.rb +69 -0
  24. data/lib/mongo_mapper/plugins/associations/proxy.rb +124 -0
  25. data/lib/mongo_mapper/plugins/callbacks.rb +240 -0
  26. data/lib/mongo_mapper/plugins/clone.rb +13 -0
  27. data/lib/mongo_mapper/plugins/descendants.rb +16 -0
  28. data/lib/mongo_mapper/plugins/dirty.rb +119 -0
  29. data/lib/mongo_mapper/plugins/equality.rb +23 -0
  30. data/lib/mongo_mapper/plugins/identity_map.rb +122 -0
  31. data/lib/mongo_mapper/plugins/inspect.rb +14 -0
  32. data/lib/mongo_mapper/plugins/keys.rb +345 -0
  33. data/lib/mongo_mapper/plugins/logger.rb +17 -0
  34. data/lib/mongo_mapper/plugins/modifiers.rb +107 -0
  35. data/lib/mongo_mapper/plugins/pagination.rb +24 -0
  36. data/lib/mongo_mapper/plugins/pagination/proxy.rb +72 -0
  37. data/lib/mongo_mapper/plugins/persistence.rb +68 -0
  38. data/lib/mongo_mapper/plugins/protected.rb +45 -0
  39. data/lib/mongo_mapper/plugins/rails.rb +57 -0
  40. data/lib/mongo_mapper/plugins/serialization.rb +91 -0
  41. data/lib/mongo_mapper/plugins/serialization/array.rb +56 -0
  42. data/lib/mongo_mapper/plugins/serialization/xml_serializer.rb +240 -0
  43. data/lib/mongo_mapper/plugins/timestamps.rb +21 -0
  44. data/lib/mongo_mapper/plugins/userstamps.rb +14 -0
  45. data/lib/mongo_mapper/plugins/validations.rb +46 -0
  46. data/lib/mongo_mapper/query.rb +143 -0
  47. data/lib/mongo_mapper/support.rb +218 -0
  48. data/lib/mongo_mapper/support/descendant_appends.rb +46 -0
  49. data/lib/mongo_mapper/support/find.rb +77 -0
  50. data/lib/mongo_mapper/version.rb +3 -0
  51. data/mongo_mapper.gemspec +214 -0
  52. data/mongo_mapper_ign.gemspec +217 -0
  53. data/performance/read_write.rb +52 -0
  54. data/specs.watchr +51 -0
  55. data/test/NOTE_ON_TESTING +1 -0
  56. data/test/active_model_lint_test.rb +13 -0
  57. data/test/functional/associations/test_belongs_to_polymorphic_proxy.rb +63 -0
  58. data/test/functional/associations/test_belongs_to_proxy.rb +101 -0
  59. data/test/functional/associations/test_in_array_proxy.rb +325 -0
  60. data/test/functional/associations/test_many_documents_as_proxy.rb +229 -0
  61. data/test/functional/associations/test_many_documents_proxy.rb +536 -0
  62. data/test/functional/associations/test_many_embedded_polymorphic_proxy.rb +176 -0
  63. data/test/functional/associations/test_many_embedded_proxy.rb +256 -0
  64. data/test/functional/associations/test_many_polymorphic_proxy.rb +302 -0
  65. data/test/functional/associations/test_one_embedded_proxy.rb +68 -0
  66. data/test/functional/associations/test_one_proxy.rb +196 -0
  67. data/test/functional/test_associations.rb +44 -0
  68. data/test/functional/test_binary.rb +27 -0
  69. data/test/functional/test_callbacks.rb +151 -0
  70. data/test/functional/test_dirty.rb +163 -0
  71. data/test/functional/test_document.rb +1219 -0
  72. data/test/functional/test_embedded_document.rb +210 -0
  73. data/test/functional/test_identity_map.rb +507 -0
  74. data/test/functional/test_indexing.rb +44 -0
  75. data/test/functional/test_logger.rb +20 -0
  76. data/test/functional/test_modifiers.rb +394 -0
  77. data/test/functional/test_pagination.rb +93 -0
  78. data/test/functional/test_protected.rb +163 -0
  79. data/test/functional/test_string_id_compatibility.rb +67 -0
  80. data/test/functional/test_timestamps.rb +64 -0
  81. data/test/functional/test_userstamps.rb +28 -0
  82. data/test/functional/test_validations.rb +342 -0
  83. data/test/models.rb +227 -0
  84. data/test/support/custom_matchers.rb +37 -0
  85. data/test/support/timing.rb +16 -0
  86. data/test/test_helper.rb +64 -0
  87. data/test/unit/associations/test_base.rb +212 -0
  88. data/test/unit/associations/test_proxy.rb +105 -0
  89. data/test/unit/serializers/test_json_serializer.rb +202 -0
  90. data/test/unit/test_descendant_appends.rb +71 -0
  91. data/test/unit/test_document.rb +225 -0
  92. data/test/unit/test_dynamic_finder.rb +123 -0
  93. data/test/unit/test_embedded_document.rb +657 -0
  94. data/test/unit/test_keys.rb +185 -0
  95. data/test/unit/test_mongo_mapper.rb +118 -0
  96. data/test/unit/test_pagination.rb +160 -0
  97. data/test/unit/test_plugins.rb +50 -0
  98. data/test/unit/test_query.rb +374 -0
  99. data/test/unit/test_rails.rb +181 -0
  100. data/test/unit/test_rails_compatibility.rb +52 -0
  101. data/test/unit/test_serialization.rb +51 -0
  102. data/test/unit/test_support.rb +382 -0
  103. data/test/unit/test_time_zones.rb +39 -0
  104. data/test/unit/test_validations.rb +544 -0
  105. metadata +327 -0
@@ -0,0 +1,50 @@
1
+ require 'test_helper'
2
+
3
+ module MyPlugin
4
+ def self.configure(model)
5
+ model.class_eval { attr_accessor :from_configure }
6
+ end
7
+
8
+ module ClassMethods
9
+ def class_foo
10
+ 'class_foo'
11
+ end
12
+ end
13
+
14
+ module InstanceMethods
15
+ def instance_foo
16
+ 'instance_foo'
17
+ end
18
+ end
19
+ end
20
+
21
+ class PluginsTest < Test::Unit::TestCase
22
+ context "plugin" do
23
+ setup do
24
+ @document = Class.new do
25
+ extend MongoMapper::Plugins
26
+ plugin MyPlugin
27
+ end
28
+ end
29
+
30
+ should "include instance methods" do
31
+ @document.new.instance_foo.should == 'instance_foo'
32
+ end
33
+
34
+ should "extend class methods" do
35
+ @document.class_foo.should == 'class_foo'
36
+ end
37
+
38
+ should "pass model to configure" do
39
+ @document.new.should respond_to(:from_configure)
40
+ end
41
+
42
+ should "default plugins to empty array" do
43
+ Class.new { extend MongoMapper::Plugins }.plugins.should == []
44
+ end
45
+
46
+ should "add plugin to plugins" do
47
+ @document.plugins.should include(MyPlugin)
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,374 @@
1
+ require 'test_helper'
2
+ require 'models'
3
+
4
+ class QueryTest < Test::Unit::TestCase
5
+ include MongoMapper
6
+
7
+ should "raise error if provided something other than a hash" do
8
+ lambda { Query.new(Room) }.should raise_error(ArgumentError)
9
+ lambda { Query.new(Room, 1) }.should raise_error(ArgumentError)
10
+ end
11
+
12
+ should "symbolize the keys of the hash provided" do
13
+ Query.new(Room, 'offset' => 1).options.keys.map do |key|
14
+ key.should be_instance_of(Symbol)
15
+ end
16
+ end
17
+
18
+ context "Converting conditions to criteria" do
19
+ should "not add _type to query if model does not have superclass that is single collection inherited" do
20
+ Query.new(Message, :foo => 'bar').criteria.should == {
21
+ :foo => 'bar'
22
+ }
23
+ end
24
+
25
+ should "not add _type to nested conditions" do
26
+ Query.new(Enter, :foo => 'bar', :age => {'$gt' => 21}).criteria.should == {
27
+ :foo => 'bar',
28
+ :age => {'$gt' => 21},
29
+ :_type => 'Enter'
30
+ }
31
+ end
32
+
33
+ should "automatically add _type to query if model is single collection inherited" do
34
+ Query.new(Enter, :foo => 'bar').criteria.should == {
35
+ :foo => 'bar',
36
+ :_type => 'Enter'
37
+ }
38
+ end
39
+
40
+ %w{gt lt gte lte ne in nin mod all size where exists}.each do |operator|
41
+ next if operator == 'size' && RUBY_VERSION >= '1.9.1' # 1.9 defines Symbol#size
42
+
43
+ should "convert #{operator} conditions" do
44
+ Query.new(Room, :age.send(operator) => 21).criteria.should == {
45
+ :age => {"$#{operator}" => 21}
46
+ }
47
+ end
48
+ end
49
+
50
+ should "normalize value when using symbol operators" do
51
+ time = Time.now.in_time_zone('Indiana (East)')
52
+ criteria = Query.new(Room, :created_at.gt => time).criteria
53
+ criteria[:created_at]['$gt'].should be_utc
54
+ end
55
+
56
+ should "work with multiple symbol operators on the same field" do
57
+ Query.new(Message, :position.gt => 0, :position.lte => 10).criteria.should == {
58
+ :position => {"$gt" => 0, "$lte" => 10}
59
+ }
60
+ end
61
+
62
+ should "work with simple criteria" do
63
+ Query.new(Room, :foo => 'bar').criteria.should == {
64
+ :foo => 'bar'
65
+ }
66
+
67
+ Query.new(Room, :foo => 'bar', :baz => 'wick').criteria.should == {
68
+ :foo => 'bar',
69
+ :baz => 'wick'
70
+ }
71
+ end
72
+
73
+ should "convert id to _id" do
74
+ id = BSON::ObjectID.new
75
+ Query.new(Room, :id => id).criteria.should == {:_id => id}
76
+ end
77
+
78
+ should "convert id with symbol operator to _id with modifier" do
79
+ id = BSON::ObjectID.new
80
+ Query.new(Room, :id.ne => id).criteria.should == {
81
+ :_id => {'$ne' => id}
82
+ }
83
+ end
84
+
85
+ should "make sure that _id's are object ids" do
86
+ id = BSON::ObjectID.new
87
+ Query.new(Room, :_id => id.to_s).criteria.should == {:_id => id}
88
+ end
89
+
90
+ should "work fine with _id's that are object ids" do
91
+ id = BSON::ObjectID.new
92
+ Query.new(Room, :_id => id).criteria.should == {:_id => id}
93
+ end
94
+
95
+ should "make sure other object id typed keys get converted" do
96
+ id = BSON::ObjectID.new
97
+ Query.new(Message, :room_id => id.to_s).criteria.should == {:room_id => id}
98
+ end
99
+
100
+ should "work fine with object ids for object id typed keys" do
101
+ id = BSON::ObjectID.new
102
+ Query.new(Message, :room_id => id).criteria.should == {:room_id => id}
103
+ end
104
+
105
+ should "convert times to utc if they aren't already" do
106
+ time = Time.now.in_time_zone('Indiana (East)')
107
+ criteria = Query.new(Room, :created_at => time).criteria
108
+ criteria[:created_at].utc?.should be_true
109
+ end
110
+
111
+ should "not funk with times already in utc" do
112
+ time = Time.now.utc
113
+ criteria = Query.new(Room, :created_at => time).criteria
114
+ criteria[:created_at].utc?.should be_true
115
+ criteria[:created_at].should == time
116
+ end
117
+
118
+ should "use $in for arrays" do
119
+ Query.new(Room, :foo => [1,2,3]).criteria.should == {
120
+ :foo => {'$in' => [1,2,3]}
121
+ }
122
+ end
123
+
124
+ should "not use $in for arrays if already using array operator" do
125
+ Query.new(Room, :foo => {'$all' => [1,2,3]}).criteria.should == {
126
+ :foo => {'$all' => [1,2,3]}
127
+ }
128
+
129
+ Query.new(Room, :foo => {'$any' => [1,2,3]}).criteria.should == {
130
+ :foo => {'$any' => [1,2,3]}
131
+ }
132
+ end
133
+
134
+ should "use $in for sets" do
135
+ Query.new(Room, :foo => Set.new([1,2,3])).criteria.should == {
136
+ :foo => {'$in' => [1,2,3]}
137
+ }
138
+ end
139
+
140
+ should "not use $in for sets if already using array operator" do
141
+ Query.new(Room, :foo => {'$all' => Set.new([1,2,3])}).criteria.should == {
142
+ :foo => {'$all' => [1,2,3]}
143
+ }
144
+
145
+ Query.new(Room, :foo => {'$any' => Set.new([1,2,3])}).criteria.should == {
146
+ :foo => {'$any' => [1,2,3]}
147
+ }
148
+ end
149
+
150
+ should "work arbitrarily deep" do
151
+ Query.new(Room, :foo => {:bar => [1,2,3]}).criteria.should == {
152
+ :foo => {:bar => {'$in' => [1,2,3]}}
153
+ }
154
+
155
+ Query.new(Room, :foo => {:bar => {'$any' => [1,2,3]}}).criteria.should == {
156
+ :foo => {:bar => {'$any' => [1,2,3]}}
157
+ }
158
+ end
159
+
160
+ should "make sure that ids in array are object ids" do
161
+ id1, id2, id3 = BSON::ObjectID.new, BSON::ObjectID.new, BSON::ObjectID.new
162
+
163
+ Query.new(Room, :_id => [id1.to_s, id2.to_s, id3.to_s]).criteria.should == {
164
+ :_id => {'$in' => [id1, id2, id3]}
165
+ }
166
+ end
167
+ end
168
+
169
+ context "ordering" do
170
+ should "single field with ascending direction" do
171
+ sort = [['foo', 1]]
172
+ Query.new(Room, :order => 'foo asc').options[:sort].should == sort
173
+ Query.new(Room, :order => 'foo ASC').options[:sort].should == sort
174
+ end
175
+
176
+ should "single field with descending direction" do
177
+ sort = [['foo', -1]]
178
+ Query.new(Room, :order => 'foo desc').options[:sort].should == sort
179
+ Query.new(Room, :order => 'foo DESC').options[:sort].should == sort
180
+ end
181
+
182
+ should "convert order operators to mongo sort" do
183
+ Query.new(Room, :order => :foo.asc).options[:sort].should == [['foo', 1]]
184
+ Query.new(Room, :order => :foo.desc).options[:sort].should == [['foo', -1]]
185
+ end
186
+
187
+ should "convert array of order operators to mongo sort" do
188
+ Query.new(Room, :order => [:foo.asc, :bar.desc]).options[:sort].should == [['foo', 1], ['bar', -1]]
189
+ end
190
+
191
+ should "convert field without direction to ascending" do
192
+ sort = [['foo', 1]]
193
+ Query.new(Room, :order => 'foo').options[:sort].should == sort
194
+ end
195
+
196
+ should "convert multiple fields with directions" do
197
+ sort = [['foo', -1], ['bar', 1], ['baz', -1]]
198
+ Query.new(Room, :order => 'foo desc, bar asc, baz desc').options[:sort].should == sort
199
+ end
200
+
201
+ should "convert multiple fields with some missing directions" do
202
+ sort = [['foo', -1], ['bar', 1], ['baz', 1]]
203
+ Query.new(Room, :order => 'foo desc, bar, baz').options[:sort].should == sort
204
+ end
205
+
206
+ should "just use sort if sort and order are present" do
207
+ sort = [['$natural', 1]]
208
+ Query.new(Room, :sort => sort, :order => 'foo asc').options[:sort].should == sort
209
+ end
210
+
211
+ should "normalize id to _id" do
212
+ Query.new(Room, :order => :id.asc).options[:sort].should == [['_id', 1]]
213
+ end
214
+
215
+ should "convert natural in order to proper" do
216
+ sort = [['$natural', 1]]
217
+ Query.new(Room, :order => '$natural asc').options[:sort].should == sort
218
+ sort = [['$natural', -1]]
219
+ Query.new(Room, :order => '$natural desc').options[:sort].should == sort
220
+ end
221
+
222
+ should "work for natural order ascending" do
223
+ Query.new(Room, :sort => {'$natural' => 1}).options[:sort]['$natural'].should == 1
224
+ end
225
+
226
+ should "work for natural order descending" do
227
+ Query.new(Room, :sort => {'$natural' => -1}).options[:sort]['$natural'].should == -1
228
+ end
229
+ end
230
+
231
+ context "skip" do
232
+ should "default to 0" do
233
+ Query.new(Room, {}).options[:skip].should == 0
234
+ end
235
+
236
+ should "use skip provided" do
237
+ Query.new(Room, :skip => 2).options[:skip].should == 2
238
+ end
239
+
240
+ should "covert string to integer" do
241
+ Query.new(Room, :skip => '2').options[:skip].should == 2
242
+ end
243
+
244
+ should "convert offset to skip" do
245
+ Query.new(Room, :offset => 1).options[:skip].should == 1
246
+ end
247
+ end
248
+
249
+ context "limit" do
250
+ should "default to 0" do
251
+ Query.new(Room, {}).options[:limit].should == 0
252
+ end
253
+
254
+ should "use limit provided" do
255
+ Query.new(Room, :limit => 2).options[:limit].should == 2
256
+ end
257
+
258
+ should "covert string to integer" do
259
+ Query.new(Room, :limit => '2').options[:limit].should == 2
260
+ end
261
+ end
262
+
263
+ context "fields" do
264
+ should "default to nil" do
265
+ Query.new(Room, {}).options[:fields].should be(nil)
266
+ end
267
+
268
+ should "be converted to nil if empty string" do
269
+ Query.new(Room, :fields => '').options[:fields].should be(nil)
270
+ end
271
+
272
+ should "be converted to nil if []" do
273
+ Query.new(Room, :fields => []).options[:fields].should be(nil)
274
+ end
275
+
276
+ should "should work with array" do
277
+ Query.new(Room, {:fields => %w(a b)}).options[:fields].should == %w(a b)
278
+ end
279
+
280
+ should "convert comma separated list to array" do
281
+ Query.new(Room, {:fields => 'a, b'}).options[:fields].should == %w(a b)
282
+ end
283
+
284
+ should "also work as select" do
285
+ Query.new(Room, :select => %w(a b)).options[:fields].should == %w(a b)
286
+ end
287
+
288
+ should "also work with select as array of symbols" do
289
+ Query.new(Room, :select => [:a, :b]).options[:fields].should == [:a, :b]
290
+ end
291
+
292
+ should "work with select as hash" do
293
+ Query.new(Room, :select => {:a => 0, :b => 1}).options[:fields].should == {:a => 0, :b => 1}
294
+ end
295
+ end
296
+
297
+ context "Condition auto-detection" do
298
+ should "know :conditions are criteria" do
299
+ finder = Query.new(Room, :conditions => {:foo => 'bar'})
300
+ finder.criteria.should == {:foo => 'bar'}
301
+ finder.options.keys.should_not include(:conditions)
302
+ end
303
+
304
+ should "know fields is an option" do
305
+ finder = Query.new(Room, :fields => ['foo'])
306
+ finder.options[:fields].should == ['foo']
307
+ finder.criteria.keys.should_not include(:fields)
308
+ end
309
+
310
+ # select gets converted to fields so just checking keys
311
+ should "know select is an option" do
312
+ finder = Query.new(Room, :select => 'foo')
313
+ finder.options.keys.should include(:sort)
314
+ finder.criteria.keys.should_not include(:select)
315
+ finder.criteria.keys.should_not include(:fields)
316
+ end
317
+
318
+ should "know skip is an option" do
319
+ finder = Query.new(Room, :skip => 10)
320
+ finder.options[:skip].should == 10
321
+ finder.criteria.keys.should_not include(:skip)
322
+ end
323
+
324
+ # offset gets converted to skip so just checking keys
325
+ should "know offset is an option" do
326
+ finder = Query.new(Room, :offset => 10)
327
+ finder.options.keys.should include(:skip)
328
+ finder.criteria.keys.should_not include(:skip)
329
+ finder.criteria.keys.should_not include(:offset)
330
+ end
331
+
332
+ should "know limit is an option" do
333
+ finder = Query.new(Room, :limit => 10)
334
+ finder.options[:limit].should == 10
335
+ finder.criteria.keys.should_not include(:limit)
336
+ end
337
+
338
+ should "know sort is an option" do
339
+ finder = Query.new(Room, :sort => [['foo', 1]])
340
+ finder.options[:sort].should == [['foo', 1]]
341
+ finder.criteria.keys.should_not include(:sort)
342
+ end
343
+
344
+ # order gets converted to sort so just checking keys
345
+ should "know order is an option" do
346
+ finder = Query.new(Room, :order => 'foo')
347
+ finder.options.keys.should include(:sort)
348
+ finder.criteria.keys.should_not include(:sort)
349
+ end
350
+
351
+ should "work with full range of things" do
352
+ query_options = Query.new(Room, {
353
+ :foo => 'bar',
354
+ :baz => true,
355
+ :sort => [['foo', 1]],
356
+ :fields => ['foo', 'baz'],
357
+ :limit => 10,
358
+ :skip => 10,
359
+ })
360
+
361
+ query_options.criteria.should == {
362
+ :foo => 'bar',
363
+ :baz => true,
364
+ }
365
+
366
+ query_options.options.should == {
367
+ :sort => [['foo', 1]],
368
+ :fields => ['foo', 'baz'],
369
+ :limit => 10,
370
+ :skip => 10,
371
+ }
372
+ end
373
+ end
374
+ end
@@ -0,0 +1,181 @@
1
+ require 'test_helper'
2
+
3
+ class TestRails < Test::Unit::TestCase
4
+ context "Document" do
5
+ setup do
6
+ @klass = Doc('Post') do
7
+ key :foo, String
8
+ end
9
+ end
10
+
11
+ context "Class methods" do
12
+ should "alias has_many to many" do
13
+ @klass.should respond_to(:has_many)
14
+ end
15
+
16
+ should "alias has_one to one" do
17
+ @klass.should respond_to(:has_one)
18
+ end
19
+
20
+ should "have column names" do
21
+ @klass.column_names.sort.should == ['_id', 'foo']
22
+ end
23
+
24
+ should "implement human_name" do
25
+ @klass.human_name.should == 'Post'
26
+ end
27
+ end
28
+
29
+ context "Instance methods" do
30
+ setup do
31
+ @klass.class_eval do
32
+ def bar=(value)
33
+ write_attribute(:foo, value)
34
+ end
35
+
36
+ def bar_before_typecast
37
+ read_attribute_before_typecast(:foo)
38
+ end
39
+
40
+ def bar
41
+ read_attribute(:foo)
42
+ end
43
+ end
44
+ end
45
+
46
+ should "alias new_record? to new?" do
47
+ @klass.new.should be_new_record
48
+ end
49
+
50
+ should "be able to read key with read_attribute" do
51
+ @klass.new(:foo => 'Bar').bar.should == 'Bar'
52
+ end
53
+
54
+ should "be able to read key before typecast with read_attribute_before_typecast" do
55
+ @klass.new(:foo => 21).bar_before_typecast.should == 21
56
+ @klass.new(:foo => 21).bar.should == '21'
57
+ end
58
+
59
+ should "be able to write key with write_attribute" do
60
+ @klass.new(:bar => 'Setting Foo').foo.should == 'Setting Foo'
61
+ end
62
+
63
+ context '#to_param' do
64
+ should "be nil if not persisted" do
65
+ @klass.new.tap do |doc|
66
+ doc.to_param.should be_nil
67
+ end
68
+ end
69
+
70
+ should "array representation of id if persisted" do
71
+ @klass.create.tap do |doc|
72
+ doc.to_param.should == doc.id.to_s
73
+ end
74
+ end
75
+ end
76
+
77
+ context '#to_key' do
78
+ should "be nil if not persisted" do
79
+ @klass.new.tap do |doc|
80
+ doc.to_key.should be_nil
81
+ end
82
+ end
83
+
84
+ should "array representation of id if persisted" do
85
+ @klass.create.tap do |doc|
86
+ doc.to_key.should == [doc.id]
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
92
+
93
+ context "EmbeddedDocument" do
94
+ setup do
95
+ @klass = EDoc('Post') { key :foo, String }
96
+ end
97
+
98
+ context "Class methods" do
99
+ should "alias has_many to many" do
100
+ @klass.should respond_to(:has_many)
101
+ end
102
+
103
+ should "alias has_one to one" do
104
+ @klass.should respond_to(:has_one)
105
+ end
106
+
107
+ should "have column names" do
108
+ @klass.column_names.sort.should == ['_id', 'foo']
109
+ end
110
+
111
+ should "implement human_name" do
112
+ @klass.human_name.should == 'Post'
113
+ end
114
+ end
115
+
116
+ context "Instance methods" do
117
+ setup do
118
+ @klass.class_eval do
119
+ def bar=(value)
120
+ write_attribute(:foo, value)
121
+ end
122
+
123
+ def bar_before_typecast
124
+ read_attribute_before_typecast(:foo)
125
+ end
126
+
127
+ def bar
128
+ read_attribute(:foo)
129
+ end
130
+ end
131
+ end
132
+
133
+ should "alias new_record? to new?" do
134
+ @klass.new.should be_new_record
135
+ end
136
+
137
+ should "be able to read key with read_attribute" do
138
+ @klass.new(:foo => 'Bar').bar.should == 'Bar'
139
+ end
140
+
141
+ should "be able to read key before typecast with read_attribute_before_typecast" do
142
+ @klass.new(:foo => 21).bar_before_typecast.should == 21
143
+ @klass.new(:foo => 21).bar.should == '21'
144
+ end
145
+
146
+ should "be able to write key with write_attribute" do
147
+ @klass.new(:bar => 'Setting Foo').foo.should == 'Setting Foo'
148
+ end
149
+
150
+ context '#to_param' do
151
+ should "be nil if not persisted" do
152
+ @klass.new.tap do |doc|
153
+ doc.to_param.should be_nil
154
+ end
155
+ end
156
+
157
+ should "array representation of id if persisted" do
158
+ @klass.new.tap do |doc|
159
+ doc.expects(:persisted?).returns(true)
160
+ doc.to_param.should == doc.id.to_s
161
+ end
162
+ end
163
+ end
164
+
165
+ context '#to_key' do
166
+ should "be nil if not persisted" do
167
+ @klass.new.tap do |doc|
168
+ doc.to_key.should be_nil
169
+ end
170
+ end
171
+
172
+ should "array representation of id if persisted" do
173
+ @klass.new.tap do |doc|
174
+ doc.expects(:persisted?).returns(true)
175
+ doc.to_key.should == [doc.id]
176
+ end
177
+ end
178
+ end
179
+ end
180
+ end
181
+ end