mongo_mapper 0.5.0

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 (69) hide show
  1. data/.gitignore +7 -0
  2. data/LICENSE +20 -0
  3. data/README.rdoc +39 -0
  4. data/Rakefile +87 -0
  5. data/VERSION +1 -0
  6. data/bin/mmconsole +55 -0
  7. data/lib/mongo_mapper.rb +92 -0
  8. data/lib/mongo_mapper/associations.rb +86 -0
  9. data/lib/mongo_mapper/associations/base.rb +83 -0
  10. data/lib/mongo_mapper/associations/belongs_to_polymorphic_proxy.rb +34 -0
  11. data/lib/mongo_mapper/associations/belongs_to_proxy.rb +22 -0
  12. data/lib/mongo_mapper/associations/many_documents_as_proxy.rb +27 -0
  13. data/lib/mongo_mapper/associations/many_documents_proxy.rb +116 -0
  14. data/lib/mongo_mapper/associations/many_embedded_polymorphic_proxy.rb +33 -0
  15. data/lib/mongo_mapper/associations/many_embedded_proxy.rb +67 -0
  16. data/lib/mongo_mapper/associations/many_polymorphic_proxy.rb +11 -0
  17. data/lib/mongo_mapper/associations/many_proxy.rb +6 -0
  18. data/lib/mongo_mapper/associations/proxy.rb +64 -0
  19. data/lib/mongo_mapper/callbacks.rb +106 -0
  20. data/lib/mongo_mapper/document.rb +317 -0
  21. data/lib/mongo_mapper/dynamic_finder.rb +35 -0
  22. data/lib/mongo_mapper/embedded_document.rb +354 -0
  23. data/lib/mongo_mapper/finder_options.rb +94 -0
  24. data/lib/mongo_mapper/key.rb +32 -0
  25. data/lib/mongo_mapper/observing.rb +50 -0
  26. data/lib/mongo_mapper/pagination.rb +51 -0
  27. data/lib/mongo_mapper/rails_compatibility/document.rb +15 -0
  28. data/lib/mongo_mapper/rails_compatibility/embedded_document.rb +27 -0
  29. data/lib/mongo_mapper/save_with_validation.rb +19 -0
  30. data/lib/mongo_mapper/serialization.rb +55 -0
  31. data/lib/mongo_mapper/serializers/json_serializer.rb +92 -0
  32. data/lib/mongo_mapper/support.rb +157 -0
  33. data/lib/mongo_mapper/validations.rb +69 -0
  34. data/mongo_mapper.gemspec +156 -0
  35. data/test/NOTE_ON_TESTING +1 -0
  36. data/test/custom_matchers.rb +48 -0
  37. data/test/functional/associations/test_belongs_to_polymorphic_proxy.rb +54 -0
  38. data/test/functional/associations/test_belongs_to_proxy.rb +46 -0
  39. data/test/functional/associations/test_many_documents_as_proxy.rb +244 -0
  40. data/test/functional/associations/test_many_embedded_polymorphic_proxy.rb +132 -0
  41. data/test/functional/associations/test_many_embedded_proxy.rb +174 -0
  42. data/test/functional/associations/test_many_polymorphic_proxy.rb +297 -0
  43. data/test/functional/associations/test_many_proxy.rb +331 -0
  44. data/test/functional/test_associations.rb +48 -0
  45. data/test/functional/test_binary.rb +18 -0
  46. data/test/functional/test_callbacks.rb +85 -0
  47. data/test/functional/test_document.rb +951 -0
  48. data/test/functional/test_embedded_document.rb +97 -0
  49. data/test/functional/test_pagination.rb +87 -0
  50. data/test/functional/test_rails_compatibility.rb +30 -0
  51. data/test/functional/test_validations.rb +279 -0
  52. data/test/models.rb +169 -0
  53. data/test/test_helper.rb +29 -0
  54. data/test/unit/serializers/test_json_serializer.rb +189 -0
  55. data/test/unit/test_association_base.rb +144 -0
  56. data/test/unit/test_document.rb +165 -0
  57. data/test/unit/test_dynamic_finder.rb +125 -0
  58. data/test/unit/test_embedded_document.rb +645 -0
  59. data/test/unit/test_finder_options.rb +193 -0
  60. data/test/unit/test_key.rb +163 -0
  61. data/test/unit/test_mongomapper.rb +28 -0
  62. data/test/unit/test_observing.rb +101 -0
  63. data/test/unit/test_pagination.rb +109 -0
  64. data/test/unit/test_rails_compatibility.rb +39 -0
  65. data/test/unit/test_serializations.rb +52 -0
  66. data/test/unit/test_support.rb +272 -0
  67. data/test/unit/test_time_zones.rb +40 -0
  68. data/test/unit/test_validations.rb +503 -0
  69. metadata +204 -0
@@ -0,0 +1,109 @@
1
+ require 'test_helper'
2
+
3
+ class PaginationTest < Test::Unit::TestCase
4
+ context "Pagination proxy" do
5
+ include MongoMapper::Pagination
6
+
7
+ should "should have accessors for subject" do
8
+ subject = [1,2,3,4,5]
9
+ collection = PaginationProxy.new(25, 2)
10
+ collection.subject = subject
11
+ collection.subject.should == subject
12
+ end
13
+
14
+ should "delegate any methods not defined to the subject" do
15
+ subject = [1,2,3,4,5]
16
+ collection = PaginationProxy.new(25, 2, 10)
17
+ collection.subject = subject
18
+ collection.size.should == 5
19
+ collection.each_with_index do |value, i|
20
+ value.should == subject[i]
21
+ end
22
+ collection[0..2].should == [1,2,3]
23
+ collection.class.should == Array
24
+ end
25
+
26
+ should "return correct value for total_entries" do
27
+ PaginationProxy.new(25, 2, 10).total_entries.should == 25
28
+ PaginationProxy.new('25', 2, 10).total_entries.should == 25
29
+ end
30
+
31
+ should "return correct value for per_page" do
32
+ PaginationProxy.new(25, 2, 10).per_page.should == 10
33
+ PaginationProxy.new(25, 2, '10').per_page.should == 10
34
+ end
35
+
36
+ should "alias limit to per_page" do
37
+ PaginationProxy.new(100, 1, 300).limit.should == 300
38
+ end
39
+
40
+ should "set per_page to 25 if nil or blank" do
41
+ PaginationProxy.new(25, 2).per_page.should == 25
42
+ PaginationProxy.new(25, 2, '').per_page.should == 25
43
+ end
44
+
45
+ should "return correct value for current_page" do
46
+ PaginationProxy.new(25, 2, 10).current_page.should == 2
47
+ PaginationProxy.new(25, '2', 10).current_page.should == 2
48
+ end
49
+
50
+ should "not allow value less than 1 for current page" do
51
+ PaginationProxy.new(25, -1).current_page.should == 1
52
+ end
53
+
54
+ should "automatically calculate total_pages from total_entries and per page" do
55
+ PaginationProxy.new(25, 2, 10).total_pages.should == 3
56
+ end
57
+
58
+ should "know how many records to skip" do
59
+ PaginationProxy.new(25, 2, 10).skip.should == 10
60
+ end
61
+
62
+ context "previous_page" do
63
+ should "be nil if current page 1" do
64
+ PaginationProxy.new(25, 1, 10).previous_page.should be_nil
65
+ end
66
+
67
+ should "be one less than current page if current is > 1" do
68
+ PaginationProxy.new(25, 2, 10).previous_page.should == 1
69
+ end
70
+ end
71
+
72
+ context "next_page" do
73
+ should "be nil if current page is last page" do
74
+ PaginationProxy.new(25, 3, 10).next_page.should be_nil
75
+ end
76
+
77
+ should "work for any page that is not last" do
78
+ PaginationProxy.new(25, 1, 10).next_page.should == 2
79
+ PaginationProxy.new(25, 2, 10).next_page.should == 3
80
+ end
81
+ end
82
+
83
+ context "previous_page" do
84
+ should "be nil if current page is first page" do
85
+ PaginationProxy.new(25, 1, 10).previous_page.should be_nil
86
+ end
87
+
88
+ should "work for any page other than first" do
89
+ PaginationProxy.new(25, 2, 10).previous_page.should == 1
90
+ PaginationProxy.new(25, 3, 10).previous_page.should == 2
91
+ end
92
+ end
93
+
94
+ context "out_of_bounds?" do
95
+ should "be true if current_page is greater than total_pages" do
96
+ PaginationProxy.new(25, 10, 4).out_of_bounds?.should be_true
97
+ end
98
+
99
+ should "be false if current_page is less than total_pages" do
100
+ PaginationProxy.new(25, 10, 1).out_of_bounds?.should be_false
101
+ PaginationProxy.new(25, 2, 10).out_of_bounds?.should be_false
102
+ end
103
+
104
+ should "be false if current_page is equal to total_pages" do
105
+ PaginationProxy.new(25, 3, 10).out_of_bounds?.should be_false
106
+ end
107
+ end
108
+ end # end of pagination proxy
109
+ end # end of test case
@@ -0,0 +1,39 @@
1
+ require 'test_helper'
2
+
3
+ class TestRailsCompatibility < Test::Unit::TestCase
4
+ class Item
5
+ include MongoMapper::EmbeddedDocument
6
+ key :for_all, String
7
+ end
8
+
9
+ class FirstItem < Item
10
+ key :first_only, String
11
+ many :second_items
12
+ end
13
+
14
+ class SecondItem < Item
15
+ key :second_only, String
16
+ end
17
+
18
+ context "EmbeddedDocument" do
19
+ should "raise error for to_param as embedded do not have id's" do
20
+ lambda { Item.new.to_param }.should raise_error
21
+ end
22
+
23
+ should "alias many to has_many" do
24
+ FirstItem.should respond_to(:has_many)
25
+ FirstItem.method(:has_many).should == FirstItem.method(:many)
26
+ end
27
+
28
+ should "have column names" do
29
+ Item.column_names.sort.should == ['_id', 'for_all']
30
+ FirstItem.column_names.sort.should == ['_id', 'first_only', 'for_all']
31
+ SecondItem.column_names.sort.should == ['_id', 'for_all', 'second_only']
32
+ end
33
+
34
+ should "alias new to new_record?" do
35
+ instance = Item.new
36
+ instance.new_record?.should == instance.new?
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,52 @@
1
+ require 'test_helper'
2
+
3
+ class SerializationTest < Test::Unit::TestCase
4
+ def setup
5
+ @document = Class.new do
6
+ include MongoMapper::EmbeddedDocument
7
+ key :name, String
8
+ key :age, Integer
9
+ key :awesome, Boolean
10
+ key :preferences, Hash
11
+ key :created_at, Time
12
+ end
13
+
14
+ @instance = @document.new(
15
+ :name => 'John Doe',
16
+ :age => 25,
17
+ :awesome => true,
18
+ :preferences => {:language => 'Ruby'},
19
+ :created_at => Time.now.change(:usec => 0)
20
+ )
21
+ end
22
+
23
+ [:json].each do |format|
24
+ context format do
25
+ should "be reversable" do
26
+ serialized = @instance.send("to_#{format}")
27
+ unserialized = @document.new.send("from_#{format}", serialized)
28
+
29
+ assert_equal @instance, unserialized
30
+ end
31
+
32
+ should "allow attribute only filtering" do
33
+ serialized = @instance.send("to_#{format}", :only => [ :age, :name ])
34
+ unserialized = @document.new.send("from_#{format}", serialized)
35
+
36
+ assert_equal @instance.name, unserialized.name
37
+ assert_equal @instance.age, unserialized.age
38
+ assert ! unserialized.awesome
39
+ assert_nil unserialized.created_at
40
+ end
41
+
42
+ should "allow attribute except filtering" do
43
+ serialized = @instance.send("to_#{format}", :except => [ :age, :name ])
44
+ unserialized = @document.new.send("from_#{format}", serialized)
45
+
46
+ assert_nil unserialized.name
47
+ assert_nil unserialized.age
48
+ assert_equal @instance.awesome, unserialized.awesome
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,272 @@
1
+ require 'test_helper'
2
+
3
+ class SupportTest < Test::Unit::TestCase
4
+ context "Array#to_mongo" do
5
+ should "convert value to_a" do
6
+ Array.to_mongo([1, 2, 3, 4]).should == [1, 2, 3, 4]
7
+ Array.to_mongo('1').should == ['1']
8
+ Array.to_mongo({'1' => '2', '3' => '4'}).should == [['1', '2'], ['3', '4']]
9
+ end
10
+ end
11
+
12
+ context "Array#from_mongo" do
13
+ should "be array if array" do
14
+ Array.from_mongo([1, 2]).should == [1, 2]
15
+ end
16
+
17
+ should "be empty array if nil" do
18
+ Array.from_mongo(nil).should == []
19
+ end
20
+ end
21
+
22
+ context "Binary#to_mongo" do
23
+ should "convert to byte buffer if not byte buffer" do
24
+ Binary.to_mongo('asdfsadasdfs').is_a?(ByteBuffer).should be_true
25
+ end
26
+
27
+ should "be byte buffer if byte buffer" do
28
+ Binary.to_mongo(ByteBuffer.new('asdfsadasdfs')).is_a?(ByteBuffer).should be_true
29
+ end
30
+
31
+ should "be nil if nil" do
32
+ Binary.to_mongo(nil).should be_nil
33
+ end
34
+ end
35
+
36
+ context "Binary#from_mongo" do
37
+ should "return value" do
38
+ buffer = ByteBuffer.new('asdfasdfasdf')
39
+ Binary.from_mongo(buffer).to_s.should == buffer.to_s
40
+ end
41
+ end
42
+
43
+ context "Boolean#to_mongo" do
44
+ should "be true for true" do
45
+ Boolean.to_mongo(true).should be_true
46
+ end
47
+
48
+ should "be false for false" do
49
+ Boolean.to_mongo(false).should be_false
50
+ end
51
+
52
+ should "handle odd assortment of other values" do
53
+ Boolean.to_mongo('true').should be_true
54
+ Boolean.to_mongo('t').should be_true
55
+ Boolean.to_mongo('1').should be_true
56
+ Boolean.to_mongo(1).should be_true
57
+
58
+ Boolean.to_mongo('false').should be_false
59
+ Boolean.to_mongo('f').should be_false
60
+ Boolean.to_mongo('0').should be_false
61
+ Boolean.to_mongo(0).should be_false
62
+ end
63
+ end
64
+
65
+ context "Boolean#from_mongo" do
66
+ should "be true for true" do
67
+ Boolean.from_mongo(true).should be_true
68
+ end
69
+
70
+ should "be false for false" do
71
+ Boolean.from_mongo(false).should be_false
72
+ end
73
+
74
+ should "be false for nil" do
75
+ Boolean.from_mongo(nil).should be_false
76
+ end
77
+ end
78
+
79
+ context "Date#to_mongo" do
80
+ should "be time if string" do
81
+ date = Date.to_mongo('10/1/2009')
82
+ date.should == Time.utc(2009, 10, 1)
83
+ date.should == date
84
+ date.month.should == 10
85
+ date.day.should == 1
86
+ date.year.should == 2009
87
+ end
88
+
89
+ should "be time if date" do
90
+ Date.to_mongo(Date.new(2009, 10, 1)).should == Time.utc(2009, 10, 1)
91
+ end
92
+
93
+ should "be nil if bogus string" do
94
+ Date.to_mongo('jdsafop874').should be_nil
95
+ end
96
+
97
+ should "be nil if empty string" do
98
+ Date.to_mongo('').should be_nil
99
+ end
100
+ end
101
+
102
+ context "Date#from_mongo" do
103
+ should "be date if date" do
104
+ date = Date.new(2009, 10, 1)
105
+ from_date = Date.from_mongo(date)
106
+ from_date.should == date
107
+ from_date.month.should == 10
108
+ from_date.day.should == 1
109
+ from_date.year.should == 2009
110
+ end
111
+
112
+ should "be date if time" do
113
+ time = Time.now
114
+ Date.from_mongo(time).should == time.to_date
115
+ end
116
+
117
+ should "be nil if nil" do
118
+ Date.from_mongo(nil).should be_nil
119
+ end
120
+ end
121
+
122
+ context "Float#to_mongo" do
123
+ should "convert value to_f" do
124
+ [21, 21.0, '21'].each do |value|
125
+ Float.to_mongo(value).should == 21.0
126
+ end
127
+ end
128
+ end
129
+
130
+ context "Hash#from_mongo" do
131
+ should "convert hash to hash with indifferent access" do
132
+ hash = Hash.from_mongo(:foo => 'bar')
133
+ hash[:foo].should == 'bar'
134
+ hash['foo'].should == 'bar'
135
+ end
136
+
137
+ should "be hash if nil" do
138
+ hash = Hash.from_mongo(nil)
139
+ hash.should == {}
140
+ hash.is_a?(HashWithIndifferentAccess).should be_true
141
+ end
142
+ end
143
+
144
+ context "Hash#to_mongo instance method" do
145
+ should "have instance method that returns self" do
146
+ hash = HashWithIndifferentAccess.new('foo' => 'bar')
147
+ hash.to_mongo.should == {'foo' => 'bar'}
148
+ end
149
+ end
150
+
151
+ context "Integer#to_mongo" do
152
+ should "convert value to integer" do
153
+ [21, 21.0, '21'].each do |value|
154
+ Integer.to_mongo(value).should == 21
155
+ end
156
+ end
157
+
158
+ should "work fine with big integers" do
159
+ [9223372036854775807, '9223372036854775807'].each do |value|
160
+ Integer.to_mongo(value).should == 9223372036854775807
161
+ end
162
+ end
163
+ end
164
+
165
+ context "NilClass#to_mongo" do
166
+ should "return nil" do
167
+ nil.to_mongo(nil).should be_nil
168
+ end
169
+ end
170
+
171
+ context "NilClass#from_mongo" do
172
+ should "return nil" do
173
+ nil.from_mongo(nil).should be_nil
174
+ end
175
+ end
176
+
177
+ context "Object#to_mongo" do
178
+ should "return value" do
179
+ Object.to_mongo(21).should == 21
180
+ Object.to_mongo('21').should == '21'
181
+ Object.to_mongo(9223372036854775807).should == 9223372036854775807
182
+ end
183
+ end
184
+
185
+ context "Object#from_mongo" do
186
+ should "return value" do
187
+ Object.from_mongo(21).should == 21
188
+ Object.from_mongo('21').should == '21'
189
+ Object.from_mongo(9223372036854775807).should == 9223372036854775807
190
+ end
191
+ end
192
+
193
+ context "String#to_mongo" do
194
+ should "convert value to_s" do
195
+ [21, '21'].each do |value|
196
+ String.to_mongo(value).should == '21'
197
+ end
198
+ end
199
+
200
+ should "be nil if nil" do
201
+ String.to_mongo(nil).should be_nil
202
+ end
203
+ end
204
+
205
+ context "String#from_mongo" do
206
+ should "be string if value present" do
207
+ String.from_mongo('Scotch! Scotch! Scotch!').should == 'Scotch! Scotch! Scotch!'
208
+ end
209
+
210
+ should "return nil if nil" do
211
+ String.from_mongo(nil).should be_nil
212
+ end
213
+
214
+ should "return empty string if blank" do
215
+ String.from_mongo('').should == ''
216
+ end
217
+ end
218
+
219
+ context "Time#to_mongo without Time.zone" do
220
+ should "be time if string" do
221
+ Time.to_mongo('2000-01-01 01:01:01.123456').should == Time.local(2000, 1, 1, 1, 1, 1, 123456).utc
222
+ end
223
+
224
+ should "be time in utc if time" do
225
+ Time.to_mongo(Time.local(2009, 8, 15, 0, 0, 0)).zone.should == 'UTC'
226
+ end
227
+
228
+ should "not be nil if nil" do
229
+ # Time.parse actually returns like right now
230
+ Time.to_mongo(nil).should_not be_nil
231
+ end
232
+ end
233
+
234
+ context "Time#to_mongo with Time.zone" do
235
+ should "be time if time" do
236
+ Time.zone = 'Hawaii'
237
+ Time.to_mongo(Time.zone.local(2009, 8, 15, 14, 0, 0)).should == Time.utc(2009, 8, 16, 0, 0, 0)
238
+ Time.zone = nil
239
+ end
240
+
241
+ should "be time if string" do
242
+ Time.zone = 'Hawaii'
243
+ Time.to_mongo('2009-08-15 14:00:00').should == Time.utc(2009, 8, 16, 0, 0, 0)
244
+ Time.zone = nil
245
+ end
246
+
247
+ should "be nil if nil" do
248
+ Time.zone = 'Hawaii'
249
+ Time.to_mongo(nil).should be_nil
250
+ Time.zone = nil
251
+ end
252
+ end
253
+
254
+ context "Time#from_mongo without Time.zone" do
255
+ should "be time" do
256
+ time = Time.now
257
+ Time.from_mongo(time).should == time
258
+ end
259
+ end
260
+
261
+ context "Time#from_mongo with Time.zone" do
262
+ should "be time in Time.zone" do
263
+ Time.zone = 'Hawaii'
264
+
265
+ time = Time.from_mongo(Time.utc(2009, 10, 1))
266
+ time.should == Time.zone.local(2009, 9, 30, 14)
267
+ time.is_a?(ActiveSupport::TimeWithZone).should be_true
268
+
269
+ Time.zone = nil
270
+ end
271
+ end
272
+ end