djsun-mongomapper 0.3.1

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 (61) hide show
  1. data/.gitignore +7 -0
  2. data/History +51 -0
  3. data/LICENSE +20 -0
  4. data/README.rdoc +39 -0
  5. data/Rakefile +71 -0
  6. data/VERSION +1 -0
  7. data/bin/mmconsole +56 -0
  8. data/lib/mongomapper.rb +96 -0
  9. data/lib/mongomapper/associations.rb +61 -0
  10. data/lib/mongomapper/associations/base.rb +71 -0
  11. data/lib/mongomapper/associations/belongs_to_polymorphic_proxy.rb +32 -0
  12. data/lib/mongomapper/associations/belongs_to_proxy.rb +22 -0
  13. data/lib/mongomapper/associations/many_documents_proxy.rb +85 -0
  14. data/lib/mongomapper/associations/many_embedded_polymorphic_proxy.rb +33 -0
  15. data/lib/mongomapper/associations/many_embedded_proxy.rb +17 -0
  16. data/lib/mongomapper/associations/many_polymorphic_proxy.rb +11 -0
  17. data/lib/mongomapper/associations/many_proxy.rb +6 -0
  18. data/lib/mongomapper/associations/proxy.rb +67 -0
  19. data/lib/mongomapper/callbacks.rb +106 -0
  20. data/lib/mongomapper/document.rb +278 -0
  21. data/lib/mongomapper/embedded_document.rb +237 -0
  22. data/lib/mongomapper/finder_options.rb +96 -0
  23. data/lib/mongomapper/key.rb +80 -0
  24. data/lib/mongomapper/observing.rb +50 -0
  25. data/lib/mongomapper/pagination.rb +52 -0
  26. data/lib/mongomapper/rails_compatibility/document.rb +15 -0
  27. data/lib/mongomapper/rails_compatibility/embedded_document.rb +25 -0
  28. data/lib/mongomapper/save_with_validation.rb +19 -0
  29. data/lib/mongomapper/serialization.rb +55 -0
  30. data/lib/mongomapper/serializers/json_serializer.rb +79 -0
  31. data/lib/mongomapper/validations.rb +47 -0
  32. data/mongomapper.gemspec +139 -0
  33. data/test/NOTE_ON_TESTING +1 -0
  34. data/test/functional/associations/test_belongs_to_polymorphic_proxy.rb +39 -0
  35. data/test/functional/associations/test_belongs_to_proxy.rb +35 -0
  36. data/test/functional/associations/test_many_embedded_polymorphic_proxy.rb +131 -0
  37. data/test/functional/associations/test_many_embedded_proxy.rb +106 -0
  38. data/test/functional/associations/test_many_polymorphic_proxy.rb +267 -0
  39. data/test/functional/associations/test_many_proxy.rb +236 -0
  40. data/test/functional/test_associations.rb +40 -0
  41. data/test/functional/test_callbacks.rb +85 -0
  42. data/test/functional/test_document.rb +691 -0
  43. data/test/functional/test_pagination.rb +81 -0
  44. data/test/functional/test_rails_compatibility.rb +31 -0
  45. data/test/functional/test_validations.rb +172 -0
  46. data/test/models.rb +108 -0
  47. data/test/test_helper.rb +67 -0
  48. data/test/unit/serializers/test_json_serializer.rb +103 -0
  49. data/test/unit/test_association_base.rb +136 -0
  50. data/test/unit/test_document.rb +125 -0
  51. data/test/unit/test_embedded_document.rb +370 -0
  52. data/test/unit/test_finder_options.rb +214 -0
  53. data/test/unit/test_key.rb +217 -0
  54. data/test/unit/test_mongo_id.rb +35 -0
  55. data/test/unit/test_mongomapper.rb +28 -0
  56. data/test/unit/test_observing.rb +101 -0
  57. data/test/unit/test_pagination.rb +113 -0
  58. data/test/unit/test_rails_compatibility.rb +34 -0
  59. data/test/unit/test_serializations.rb +52 -0
  60. data/test/unit/test_validations.rb +259 -0
  61. metadata +189 -0
@@ -0,0 +1,214 @@
1
+ require 'test_helper'
2
+
3
+ class FinderOptionsTest < Test::Unit::TestCase
4
+ include MongoMapper
5
+
6
+ should "raise error if provided something other than a hash" do
7
+ lambda { FinderOptions.new }.should raise_error(ArgumentError)
8
+ lambda { FinderOptions.new(1) }.should raise_error(ArgumentError)
9
+ end
10
+
11
+ should "have symbolize the keys of the hash provided" do
12
+ FinderOptions.new('offset' => 1).options.keys.map do |key|
13
+ key.should be_instance_of(Symbol)
14
+ end
15
+ end
16
+
17
+ context "#criteria" do
18
+ should "convert conditions to criteria" do
19
+ FinderOptions.expects(:to_mongo_criteria).with(:foo => 1).returns({})
20
+ FinderOptions.new(:conditions => {:foo => 1}).criteria
21
+ end
22
+ end
23
+
24
+ context "#options" do
25
+ should "convert options to mongo options" do
26
+ FinderOptions.expects(:to_mongo_options).with(:order => 'foo asc', :select => 'foo,bar').returns({})
27
+ FinderOptions.new(:order => 'foo asc', :select => 'foo,bar').options
28
+ end
29
+ end
30
+
31
+
32
+ context "Converting conditions to criteria" do
33
+ should "work with simple criteria" do
34
+ FinderOptions.to_mongo_criteria(:foo => 'bar').should == {
35
+ :foo => 'bar'
36
+ }
37
+
38
+ FinderOptions.to_mongo_criteria(:foo => 'bar', :baz => 'wick').should == {
39
+ :foo => 'bar',
40
+ :baz => 'wick'
41
+ }
42
+ end
43
+
44
+ should "use $in for arrays" do
45
+ FinderOptions.to_mongo_criteria(:foo => [1,2,3]).should == {
46
+ :foo => {'$in' => [1,2,3]}
47
+ }
48
+ end
49
+
50
+ should "not use $in for arrays if already using array modifier" do
51
+ FinderOptions.to_mongo_criteria(:foo => {'$all' => [1,2,3]}).should == {
52
+ :foo => {'$all' => [1,2,3]}
53
+ }
54
+ end
55
+
56
+ should "work arbitrarily deep" do
57
+ FinderOptions.to_mongo_criteria(:foo => {:bar => [1,2,3]}).should == {
58
+ :foo => {:bar => {'$in' => [1,2,3]}}
59
+ }
60
+ end
61
+
62
+ should "convert string _ids to objectid automatically" do
63
+ id = XGen::Mongo::Driver::ObjectID.new
64
+
65
+ FinderOptions.to_mongo_criteria(:_id => id.to_s).should == {
66
+ :_id => id
67
+ }
68
+ end
69
+
70
+ should "leave objectid _ids alone" do
71
+ id = XGen::Mongo::Driver::ObjectID.new
72
+
73
+ FinderOptions.to_mongo_criteria(:_id => id).should == {
74
+ :_id => id
75
+ }
76
+ end
77
+
78
+ should "convert array of string _ids to object ids" do
79
+ id1 = XGen::Mongo::Driver::ObjectID.new
80
+ id2 = XGen::Mongo::Driver::ObjectID.new
81
+
82
+ FinderOptions.to_mongo_criteria(:_id => [id1.to_s, id2.to_s]).should == {
83
+ :_id => {'$in' => [id1, id2]}
84
+ }
85
+ end
86
+
87
+ should "convert array of string _ids when using mongo array stuff" do
88
+ id1 = XGen::Mongo::Driver::ObjectID.new
89
+ id2 = XGen::Mongo::Driver::ObjectID.new
90
+
91
+ FinderOptions.to_mongo_criteria(:_id => {'$all' => [id1.to_s, id2.to_s]}).should == {
92
+ :_id => {'$all' => [id1, id2]}
93
+ }
94
+
95
+ FinderOptions.to_mongo_criteria(:_id => {'$any' => [id1.to_s, id2.to_s]}).should == {
96
+ :_id => {'$any' => [id1, id2]}
97
+ }
98
+ end
99
+ end
100
+
101
+ context "ordering" do
102
+ should "single field with ascending direction" do
103
+ hash = OrderedHash.new
104
+ hash[:foo] = 1
105
+ FinderOptions.to_mongo_options(:order => 'foo asc')[:sort].should == hash
106
+ FinderOptions.to_mongo_options(:order => 'foo ASC')[:sort].should == hash
107
+ end
108
+
109
+ should "single field with descending direction" do
110
+ hash = OrderedHash.new
111
+ hash[:foo] = -1
112
+ FinderOptions.to_mongo_options(:order => 'foo desc')[:sort].should == hash
113
+ FinderOptions.to_mongo_options(:order => 'foo DESC')[:sort].should == hash
114
+ end
115
+
116
+ should "convert field without direction to ascending" do
117
+ hash = OrderedHash.new
118
+ hash[:foo] = 1
119
+ FinderOptions.to_mongo_options(:order => 'foo')[:sort].should == hash
120
+ end
121
+
122
+ should "convert multiple fields with directions" do
123
+ hash = OrderedHash.new
124
+ hash[:foo] = -1
125
+ hash[:bar] = 1
126
+ hash[:baz] = -1
127
+ FinderOptions.to_mongo_options(:order => 'foo desc, bar asc, baz desc')[:sort].should == hash
128
+ end
129
+
130
+ should "convert multiple fields with some missing directions" do
131
+ hash = OrderedHash.new
132
+ hash[:foo] = -1
133
+ hash[:bar] = 1
134
+ hash[:baz] = 1
135
+ FinderOptions.to_mongo_options(:order => 'foo desc, bar, baz')[:sort].should == hash
136
+ end
137
+
138
+ should "just use sort if sort and order are present" do
139
+ FinderOptions.to_mongo_options(:sort => {'$natural' => 1}, :order => 'foo asc')[:sort].should == {
140
+ '$natural' => 1
141
+ }
142
+ end
143
+
144
+ should "convert natural in order to proper" do
145
+ hash = OrderedHash.new
146
+ hash[:'$natural'] = 1
147
+ FinderOptions.to_mongo_options(:order => '$natural asc')[:sort].should == hash
148
+ hash[:'$natural'] = -1
149
+ FinderOptions.to_mongo_options(:order => '$natural desc')[:sort].should == hash
150
+ end
151
+
152
+ should "work for natural order ascending" do
153
+ FinderOptions.to_mongo_options(:sort => {'$natural' => 1})[:sort]['$natural'].should == 1
154
+ end
155
+
156
+ should "work for natural order descending" do
157
+ FinderOptions.to_mongo_options(:sort => {'$natural' => -1})[:sort]['$natural'].should == -1
158
+ end
159
+ end
160
+
161
+ context "offset" do
162
+ should "default to 0" do
163
+ FinderOptions.to_mongo_options({})[:offset].should == 0
164
+ end
165
+
166
+ should "use offset provided" do
167
+ FinderOptions.to_mongo_options(:offset => 2)[:offset].should == 2
168
+ end
169
+
170
+ should "covert string to integer" do
171
+ FinderOptions.to_mongo_options(:offset => '2')[:offset].should == 2
172
+ end
173
+ end
174
+
175
+ context "limit" do
176
+ should "default to 0" do
177
+ FinderOptions.to_mongo_options({})[:limit].should == 0
178
+ end
179
+
180
+ should "use offset provided" do
181
+ FinderOptions.to_mongo_options(:limit => 2)[:limit].should == 2
182
+ end
183
+
184
+ should "covert string to integer" do
185
+ FinderOptions.to_mongo_options(:limit => '2')[:limit].should == 2
186
+ end
187
+ end
188
+
189
+ context "fields" do
190
+ should "default to nil" do
191
+ FinderOptions.to_mongo_options({})[:fields].should be(nil)
192
+ end
193
+
194
+ should "be converted to nil if empty string" do
195
+ FinderOptions.to_mongo_options(:fields => '')[:fields].should be(nil)
196
+ end
197
+
198
+ should "be converted to nil if []" do
199
+ FinderOptions.to_mongo_options(:fields => [])[:fields].should be(nil)
200
+ end
201
+
202
+ should "should work with array" do
203
+ FinderOptions.to_mongo_options({:fields => %w(a b)})[:fields].should == %w(a b)
204
+ end
205
+
206
+ should "convert comma separated list to array" do
207
+ FinderOptions.to_mongo_options({:fields => 'a, b'})[:fields].should == %w(a b)
208
+ end
209
+
210
+ should "also work as select" do
211
+ FinderOptions.new(:select => %w(a b)).options[:fields].should == %w(a b)
212
+ end
213
+ end
214
+ end # FinderOptionsTest
@@ -0,0 +1,217 @@
1
+ require 'test_helper'
2
+
3
+ class Address
4
+ include MongoMapper::EmbeddedDocument
5
+
6
+ key :address, String
7
+ key :city, String
8
+ key :state, String
9
+ key :zip, Integer
10
+ end
11
+
12
+ class KeyTest < Test::Unit::TestCase
13
+ include MongoMapper
14
+
15
+ context "The Key Class" do
16
+ should "have the native types defined" do
17
+ Key::NativeTypes.should == [String, Float, Time, Integer, Boolean, Array, Hash, MongoID]
18
+ end
19
+ end
20
+
21
+ context "Initializing a new key" do
22
+ should "allow setting the name" do
23
+ Key.new(:foo, String).name.should == 'foo'
24
+ end
25
+
26
+ should "allow setting the type" do
27
+ Key.new(:foo, Integer).type.should be(Integer)
28
+ end
29
+
30
+ should "allow setting options" do
31
+ Key.new(:foo, Integer, :required => true).options[:required].should be(true)
32
+ end
33
+
34
+ should "default options to {}" do
35
+ Key.new(:foo, Integer, nil).options.should == {}
36
+ end
37
+
38
+ should "symbolize option keys" do
39
+ Key.new(:foo, Integer, 'required' => true).options[:required].should be(true)
40
+ end
41
+ end
42
+
43
+ context "A key" do
44
+ should "be equal to another key with same name and type" do
45
+ Key.new(:name, String).should == Key.new(:name, String)
46
+ end
47
+
48
+ should "not be equal to another key with different name" do
49
+ Key.new(:name, String).should_not == Key.new(:foo, String)
50
+ end
51
+
52
+ should "not be equal to another key with different type" do
53
+ Key.new(:name, String).should_not == Key.new(:name, Integer)
54
+ end
55
+
56
+ should "know if it is native" do
57
+ Key.new(:name, String).native?.should be_true
58
+ end
59
+
60
+ should "know if it is not native" do
61
+ klass = Class.new
62
+ Key.new(:name, klass).native?.should be_false
63
+ end
64
+
65
+ should "know if it is a embedded_document" do
66
+ klass = Class.new do
67
+ include MongoMapper::EmbeddedDocument
68
+ end
69
+ Key.new(:name, klass).embedded_document?.should be_true
70
+ end
71
+
72
+ should "know if it is not a embedded_document" do
73
+ Key.new(:name, String).embedded_document?.should be_false
74
+ end
75
+ end
76
+
77
+ context "setting a value" do
78
+ should "correctly typecast MongoIDs" do
79
+ key = Key.new(:_id, MongoID)
80
+ id = MongoID.new
81
+ [id, id.to_s].each do |a|
82
+ key.set(a).should == id
83
+ end
84
+ end
85
+
86
+ should "correctly typecast Strings" do
87
+ key = Key.new(:foo, String)
88
+ [21, '21'].each do |a|
89
+ key.set(a).should == '21'
90
+ end
91
+ end
92
+
93
+ should "correctly typecast Integers" do
94
+ key = Key.new(:foo, Integer)
95
+ [21, 21.0, '21'].each do |a|
96
+ key.set(a).should == 21
97
+ end
98
+ end
99
+
100
+ should "correctly typecast Floats" do
101
+ key = Key.new(:foo, Float)
102
+ [21, 21.0, '21'].each do |a|
103
+ key.set(a).should == 21.0
104
+ end
105
+ end
106
+
107
+ should "correctly typecast Times" do
108
+ key = Key.new(:foo, Time)
109
+ key.set('2000-01-01 01:01:01.123456').should == Time.local(2000, 1, 1, 1, 1, 1, 123456)
110
+ end
111
+
112
+ should_eventually "correctly typecast Times into UTC time zone" do
113
+ key = Key.new(:foo, Time)
114
+ key.set('2000-01-01 01:01:01.123456').zone.should == "UTC"
115
+ end
116
+
117
+ should_eventually "correctly typecast Dates" do
118
+ key = Key.new(:foo, Date)
119
+ key.set('2000-01-01').should == Date.new(2000, 1, 1)
120
+ end
121
+
122
+ should "correctly typecast Boolean" do
123
+ key = Key.new(:foo, Boolean)
124
+ ['false', false, 'f', '0', 0].each do |b|
125
+ key.set(b).should == false
126
+ end
127
+
128
+ ['true', true, 't', '1', 1].each do |b|
129
+ key.set(b).should == true
130
+ end
131
+ end
132
+
133
+ should "correctly typecast Array" do
134
+ key = Key.new(:foo, Array)
135
+ key.set([1,2,3,4]).should == [1,2,3,4]
136
+ key.set({'1' => '2', '3' => '4'}).should == [['1', '2'], ['3', '4']]
137
+ key.set('1').should == ['1']
138
+ end
139
+
140
+ should "correctly typecast Hash using indifferent access" do
141
+ key = Key.new(:foo, Hash)
142
+ key.set(:foo => 'bar')[:foo].should == 'bar'
143
+ key.set(:foo => 'bar')['foo'].should == 'bar'
144
+ key.set(:foo => {:bar => 'baz'})[:foo][:bar].should == 'baz'
145
+ key.set(:foo => {:bar => 'baz'})['foo']['bar'].should == 'baz'
146
+ end
147
+ end
148
+
149
+ context "getting a value" do
150
+ should "work" do
151
+ key = Key.new(:foo, String)
152
+ key.get('bar').should == 'bar'
153
+ end
154
+
155
+ context "for a key with a default value set" do
156
+ setup do
157
+ @key = Key.new(:foo, String, :default => 'baz')
158
+ end
159
+
160
+ should "return default value if value nil" do
161
+ @key.get(nil).should == 'baz'
162
+ end
163
+
164
+ should "return value if not blank" do
165
+ @key.get('foobar').should == 'foobar'
166
+ end
167
+ end
168
+
169
+ context "for a boolean key" do
170
+ should "allow setting default to false" do
171
+ Key.new(:active, Boolean, :default => false).get(nil).should be_false
172
+ end
173
+
174
+ should "allow setting default to true" do
175
+ Key.new(:active, Boolean, :default => true).get(nil).should be_true
176
+ end
177
+ end
178
+
179
+ context "for an array" do
180
+ should "return array" do
181
+ key = Key.new(:foo, Array)
182
+ key.get([1,2]).should == [1,2]
183
+ end
184
+
185
+ should "default to empty array" do
186
+ key = Key.new(:foo, Array)
187
+ key.get(nil).should == []
188
+ end
189
+ end
190
+
191
+ context "for a hash" do
192
+ should "default to empty hash" do
193
+ key = Key.new(:foo, Hash)
194
+ key.get(nil).should == {}
195
+ end
196
+
197
+ should "use hash with indifferent access" do
198
+ key = Key.new(:foo, Hash)
199
+ key.get({:foo => 'bar'})['foo'].should == 'bar'
200
+ key.get({:foo => 'bar'})[:foo].should == 'bar'
201
+ end
202
+ end
203
+
204
+ context "for a embedded_document" do
205
+ should "default to nil" do
206
+ key = Key.new(:foo, Address)
207
+ key.get(nil).should be_nil
208
+ end
209
+
210
+ should "return instance if instance" do
211
+ address = Address.new(:city => 'South Bend', :state => 'IN', :zip => 46544)
212
+ key = Key.new(:foo, Address)
213
+ key.get(address).should == address
214
+ end
215
+ end
216
+ end
217
+ end # KeyTest
@@ -0,0 +1,35 @@
1
+ require 'test_helper'
2
+
3
+ class MongoIDTest < Test::Unit::TestCase
4
+ PhonyError = Class.new(StandardError)
5
+
6
+ class Phony
7
+ def to_s
8
+ raise PhonyError
9
+ end
10
+ end
11
+
12
+ context "mm_typecast" do
13
+ should "return value if object id" do
14
+ id = XGen::Mongo::Driver::ObjectID.new
15
+ MongoID.mm_typecast(id).should == id
16
+ end
17
+
18
+ should "return object id if string" do
19
+ id = XGen::Mongo::Driver::ObjectID.new
20
+ MongoID.mm_typecast(id.to_s).should == id
21
+ end
22
+
23
+ should_eventually "raise MongoMapper::IllegalID if invalid id" do
24
+ lambda {
25
+ MongoID.mm_typecast(1234)
26
+ }.should raise_error(MongoMapper::IllegalID)
27
+ end
28
+
29
+ should "raise exception if message does not match illegal object id" do
30
+ lambda {
31
+ MongoID.mm_typecast(Phony.new)
32
+ }.should raise_error(PhonyError)
33
+ end
34
+ end
35
+ end