hashrocket-mongomapper 0.3.3

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 (62) hide show
  1. data/.gitignore +7 -0
  2. data/History +70 -0
  3. data/LICENSE +20 -0
  4. data/README.rdoc +39 -0
  5. data/Rakefile +73 -0
  6. data/VERSION +1 -0
  7. data/bin/mmconsole +56 -0
  8. data/lib/mongomapper.rb +70 -0
  9. data/lib/mongomapper/associations.rb +84 -0
  10. data/lib/mongomapper/associations/base.rb +69 -0
  11. data/lib/mongomapper/associations/belongs_to_polymorphic_proxy.rb +34 -0
  12. data/lib/mongomapper/associations/belongs_to_proxy.rb +22 -0
  13. data/lib/mongomapper/associations/many_documents_proxy.rb +103 -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 +63 -0
  19. data/lib/mongomapper/callbacks.rb +106 -0
  20. data/lib/mongomapper/document.rb +337 -0
  21. data/lib/mongomapper/dynamic_finder.rb +38 -0
  22. data/lib/mongomapper/embedded_document.rb +267 -0
  23. data/lib/mongomapper/finder_options.rb +85 -0
  24. data/lib/mongomapper/key.rb +76 -0
  25. data/lib/mongomapper/observing.rb +50 -0
  26. data/lib/mongomapper/pagination.rb +52 -0
  27. data/lib/mongomapper/rails_compatibility/document.rb +15 -0
  28. data/lib/mongomapper/rails_compatibility/embedded_document.rb +25 -0
  29. data/lib/mongomapper/save_with_validation.rb +19 -0
  30. data/lib/mongomapper/serialization.rb +55 -0
  31. data/lib/mongomapper/serializers/json_serializer.rb +92 -0
  32. data/lib/mongomapper/support.rb +30 -0
  33. data/lib/mongomapper/validations.rb +61 -0
  34. data/mongomapper.gemspec +142 -0
  35. data/test/NOTE_ON_TESTING +1 -0
  36. data/test/functional/associations/test_belongs_to_polymorphic_proxy.rb +53 -0
  37. data/test/functional/associations/test_belongs_to_proxy.rb +45 -0
  38. data/test/functional/associations/test_many_embedded_polymorphic_proxy.rb +131 -0
  39. data/test/functional/associations/test_many_embedded_proxy.rb +106 -0
  40. data/test/functional/associations/test_many_polymorphic_proxy.rb +261 -0
  41. data/test/functional/associations/test_many_proxy.rb +295 -0
  42. data/test/functional/test_associations.rb +47 -0
  43. data/test/functional/test_callbacks.rb +85 -0
  44. data/test/functional/test_document.rb +952 -0
  45. data/test/functional/test_pagination.rb +81 -0
  46. data/test/functional/test_rails_compatibility.rb +30 -0
  47. data/test/functional/test_validations.rb +172 -0
  48. data/test/models.rb +139 -0
  49. data/test/test_helper.rb +67 -0
  50. data/test/unit/serializers/test_json_serializer.rb +157 -0
  51. data/test/unit/test_association_base.rb +144 -0
  52. data/test/unit/test_document.rb +123 -0
  53. data/test/unit/test_embedded_document.rb +526 -0
  54. data/test/unit/test_finder_options.rb +183 -0
  55. data/test/unit/test_key.rb +247 -0
  56. data/test/unit/test_mongomapper.rb +28 -0
  57. data/test/unit/test_observing.rb +101 -0
  58. data/test/unit/test_pagination.rb +113 -0
  59. data/test/unit/test_rails_compatibility.rb +34 -0
  60. data/test/unit/test_serializations.rb +52 -0
  61. data/test/unit/test_validations.rb +500 -0
  62. metadata +189 -0
@@ -0,0 +1,183 @@
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
+ context "Converting conditions to criteria" do
32
+ should "work with simple criteria" do
33
+ FinderOptions.to_mongo_criteria(:foo => 'bar').should == {
34
+ :foo => 'bar'
35
+ }
36
+
37
+ FinderOptions.to_mongo_criteria(:foo => 'bar', :baz => 'wick').should == {
38
+ :foo => 'bar',
39
+ :baz => 'wick'
40
+ }
41
+ end
42
+
43
+ should "use $in for arrays" do
44
+ FinderOptions.to_mongo_criteria(:foo => [1,2,3]).should == {
45
+ :foo => {'$in' => [1,2,3]}
46
+ }
47
+ end
48
+
49
+ should "not use $in for arrays if already using array operator" do
50
+ FinderOptions.to_mongo_criteria(:foo => {'$all' => [1,2,3]}).should == {
51
+ :foo => {'$all' => [1,2,3]}
52
+ }
53
+
54
+ FinderOptions.to_mongo_criteria(:foo => {'$any' => [1,2,3]}).should == {
55
+ :foo => {'$any' => [1,2,3]}
56
+ }
57
+ end
58
+
59
+ should "work arbitrarily deep" do
60
+ FinderOptions.to_mongo_criteria(:foo => {:bar => [1,2,3]}).should == {
61
+ :foo => {:bar => {'$in' => [1,2,3]}}
62
+ }
63
+
64
+ FinderOptions.to_mongo_criteria(:foo => {:bar => {'$any' => [1,2,3]}}).should == {
65
+ :foo => {:bar => {'$any' => [1,2,3]}}
66
+ }
67
+ end
68
+ end
69
+
70
+ context "ordering" do
71
+ should "single field with ascending direction" do
72
+ hash = OrderedHash.new
73
+ hash[:foo] = 1
74
+ FinderOptions.to_mongo_options(:order => 'foo asc')[:sort].should == hash
75
+ FinderOptions.to_mongo_options(:order => 'foo ASC')[:sort].should == hash
76
+ end
77
+
78
+ should "single field with descending direction" do
79
+ hash = OrderedHash.new
80
+ hash[:foo] = -1
81
+ FinderOptions.to_mongo_options(:order => 'foo desc')[:sort].should == hash
82
+ FinderOptions.to_mongo_options(:order => 'foo DESC')[:sort].should == hash
83
+ end
84
+
85
+ should "convert field without direction to ascending" do
86
+ hash = OrderedHash.new
87
+ hash[:foo] = 1
88
+ FinderOptions.to_mongo_options(:order => 'foo')[:sort].should == hash
89
+ end
90
+
91
+ should "convert multiple fields with directions" do
92
+ hash = OrderedHash.new
93
+ hash[:foo] = -1
94
+ hash[:bar] = 1
95
+ hash[:baz] = -1
96
+ FinderOptions.to_mongo_options(:order => 'foo desc, bar asc, baz desc')[:sort].should == hash
97
+ end
98
+
99
+ should "convert multiple fields with some missing directions" do
100
+ hash = OrderedHash.new
101
+ hash[:foo] = -1
102
+ hash[:bar] = 1
103
+ hash[:baz] = 1
104
+ FinderOptions.to_mongo_options(:order => 'foo desc, bar, baz')[:sort].should == hash
105
+ end
106
+
107
+ should "just use sort if sort and order are present" do
108
+ FinderOptions.to_mongo_options(:sort => {'$natural' => 1}, :order => 'foo asc')[:sort].should == {
109
+ '$natural' => 1
110
+ }
111
+ end
112
+
113
+ should "convert natural in order to proper" do
114
+ hash = OrderedHash.new
115
+ hash[:'$natural'] = 1
116
+ FinderOptions.to_mongo_options(:order => '$natural asc')[:sort].should == hash
117
+ hash[:'$natural'] = -1
118
+ FinderOptions.to_mongo_options(:order => '$natural desc')[:sort].should == hash
119
+ end
120
+
121
+ should "work for natural order ascending" do
122
+ FinderOptions.to_mongo_options(:sort => {'$natural' => 1})[:sort]['$natural'].should == 1
123
+ end
124
+
125
+ should "work for natural order descending" do
126
+ FinderOptions.to_mongo_options(:sort => {'$natural' => -1})[:sort]['$natural'].should == -1
127
+ end
128
+ end
129
+
130
+ context "offset" do
131
+ should "default to 0" do
132
+ FinderOptions.to_mongo_options({})[:offset].should == 0
133
+ end
134
+
135
+ should "use offset provided" do
136
+ FinderOptions.to_mongo_options(:offset => 2)[:offset].should == 2
137
+ end
138
+
139
+ should "covert string to integer" do
140
+ FinderOptions.to_mongo_options(:offset => '2')[:offset].should == 2
141
+ end
142
+ end
143
+
144
+ context "limit" do
145
+ should "default to 0" do
146
+ FinderOptions.to_mongo_options({})[:limit].should == 0
147
+ end
148
+
149
+ should "use offset provided" do
150
+ FinderOptions.to_mongo_options(:limit => 2)[:limit].should == 2
151
+ end
152
+
153
+ should "covert string to integer" do
154
+ FinderOptions.to_mongo_options(:limit => '2')[:limit].should == 2
155
+ end
156
+ end
157
+
158
+ context "fields" do
159
+ should "default to nil" do
160
+ FinderOptions.to_mongo_options({})[:fields].should be(nil)
161
+ end
162
+
163
+ should "be converted to nil if empty string" do
164
+ FinderOptions.to_mongo_options(:fields => '')[:fields].should be(nil)
165
+ end
166
+
167
+ should "be converted to nil if []" do
168
+ FinderOptions.to_mongo_options(:fields => [])[:fields].should be(nil)
169
+ end
170
+
171
+ should "should work with array" do
172
+ FinderOptions.to_mongo_options({:fields => %w(a b)})[:fields].should == %w(a b)
173
+ end
174
+
175
+ should "convert comma separated list to array" do
176
+ FinderOptions.to_mongo_options({:fields => 'a, b'})[:fields].should == %w(a b)
177
+ end
178
+
179
+ should "also work as select" do
180
+ FinderOptions.new(:select => %w(a b)).options[:fields].should == %w(a b)
181
+ end
182
+ end
183
+ end # FinderOptionsTest
@@ -0,0 +1,247 @@
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]
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
+
42
+ should "work with just name" do
43
+ key = Key.new(:foo)
44
+ key.name.should == 'foo'
45
+ end
46
+
47
+ should "work with name and type" do
48
+ key = Key.new(:foo, String)
49
+ key.name.should == 'foo'
50
+ key.type.should == String
51
+ end
52
+
53
+ should "work with name, type, and options" do
54
+ key = Key.new(:foo, String, :required => true)
55
+ key.name.should == 'foo'
56
+ key.type.should == String
57
+ key.options[:required].should be_true
58
+ end
59
+
60
+ should "work with name and options" do
61
+ key = Key.new(:foo, :required => true)
62
+ key.name.should == 'foo'
63
+ key.options[:required].should be_true
64
+ end
65
+ end
66
+
67
+ context "A key" do
68
+ should "be equal to another key with same name and type" do
69
+ Key.new(:name, String).should == Key.new(:name, String)
70
+ end
71
+
72
+ should "not be equal to another key with different name" do
73
+ Key.new(:name, String).should_not == Key.new(:foo, String)
74
+ end
75
+
76
+ should "not be equal to another key with different type" do
77
+ Key.new(:name, String).should_not == Key.new(:name, Integer)
78
+ end
79
+
80
+ context "native?" do
81
+ should "be true if native type" do
82
+ Key.new(:name, String).native?.should be_true
83
+ end
84
+
85
+ should "be true if no type" do
86
+ Key.new(:name).native?.should be_true
87
+ end
88
+
89
+ should "be false if not native" do
90
+ Key.new(:name, Class.new).native?.should be_false
91
+ end
92
+ end
93
+
94
+ should "know if it is a embedded_document" do
95
+ klass = Class.new do
96
+ include MongoMapper::EmbeddedDocument
97
+ end
98
+ Key.new(:name, klass).embedded_document?.should be_true
99
+ end
100
+
101
+ should "know if it is not a embedded_document" do
102
+ Key.new(:name, String).embedded_document?.should be_false
103
+ end
104
+ end
105
+
106
+ context "setting a value" do
107
+ should "correctly typecast Strings" do
108
+ key = Key.new(:foo, String)
109
+ [21, '21'].each do |a|
110
+ key.set(a).should == '21'
111
+ end
112
+ end
113
+
114
+ should "correctly typecast Integers" do
115
+ key = Key.new(:foo, Integer)
116
+ [21, 21.0, '21'].each do |a|
117
+ key.set(a).should == 21
118
+ end
119
+ end
120
+
121
+ should "work fine with long integers" do
122
+ key = Key.new(:foo, Integer)
123
+ [9223372036854775807, '9223372036854775807'].each do |value|
124
+ key.set(value).should == 9223372036854775807
125
+ end
126
+ end
127
+
128
+ should "correctly typecast Floats" do
129
+ key = Key.new(:foo, Float)
130
+ [21, 21.0, '21'].each do |a|
131
+ key.set(a).should == 21.0
132
+ end
133
+ end
134
+
135
+ should "correctly typecast Times" do
136
+ key = Key.new(:foo, Time)
137
+ key.set('2000-01-01 01:01:01.123456').should == Time.local(2000, 1, 1, 1, 1, 1, 123456)
138
+ end
139
+
140
+ should "correctly typecast Times into UTC time zone" do
141
+ key = Key.new(:foo, Time)
142
+ key.set('2000-01-01 01:01:01.123456').zone.should == "UTC"
143
+ end
144
+
145
+ should "correctly typecast Boolean" do
146
+ key = Key.new(:foo, Boolean)
147
+ ['false', false, 'f', '0', 0].each do |b|
148
+ key.set(b).should == false
149
+ end
150
+
151
+ ['true', true, 't', '1', 1].each do |b|
152
+ key.set(b).should == true
153
+ end
154
+ end
155
+
156
+ should "correctly typecast Array" do
157
+ key = Key.new(:foo, Array)
158
+ key.set([1,2,3,4]).should == [1,2,3,4]
159
+ key.set({'1' => '2', '3' => '4'}).should == [['1', '2'], ['3', '4']]
160
+ key.set('1').should == ['1']
161
+ end
162
+
163
+ should "correctly typecast Hash using indifferent access" do
164
+ key = Key.new(:foo, Hash)
165
+ key.set(:foo => 'bar')[:foo].should == 'bar'
166
+ key.set(:foo => 'bar')['foo'].should == 'bar'
167
+ key.set(:foo => {:bar => 'baz'})[:foo][:bar].should == 'baz'
168
+ key.set(:foo => {:bar => 'baz'})['foo']['bar'].should == 'baz'
169
+ end
170
+ end
171
+
172
+ context "getting a value" do
173
+ should "work" do
174
+ key = Key.new(:foo, String)
175
+ key.get('bar').should == 'bar'
176
+ end
177
+
178
+ should "work without type" do
179
+ key = Key.new(:foo)
180
+ key.get([1,"2"]).should == [1, "2"]
181
+ key.get(false).should == false
182
+ key.get({}).should == {}
183
+ end
184
+
185
+ context "for a key with a default value set" do
186
+ setup do
187
+ @key = Key.new(:foo, String, :default => 'baz')
188
+ end
189
+
190
+ should "return default value if value nil" do
191
+ @key.get(nil).should == 'baz'
192
+ end
193
+
194
+ should "return value if not blank" do
195
+ @key.get('foobar').should == 'foobar'
196
+ end
197
+ end
198
+
199
+ context "for a boolean key" do
200
+ should "allow setting default to false" do
201
+ Key.new(:active, Boolean, :default => false).get(nil).should be_false
202
+ end
203
+
204
+ should "allow setting default to true" do
205
+ Key.new(:active, Boolean, :default => true).get(nil).should be_true
206
+ end
207
+ end
208
+
209
+ context "for an array" do
210
+ should "return array" do
211
+ key = Key.new(:foo, Array)
212
+ key.get([1,2]).should == [1,2]
213
+ end
214
+
215
+ should "default to empty array" do
216
+ key = Key.new(:foo, Array)
217
+ key.get(nil).should == []
218
+ end
219
+ end
220
+
221
+ context "for a hash" do
222
+ should "default to empty hash" do
223
+ key = Key.new(:foo, Hash)
224
+ key.get(nil).should == {}
225
+ end
226
+
227
+ should "use hash with indifferent access" do
228
+ key = Key.new(:foo, Hash)
229
+ key.get({:foo => 'bar'})['foo'].should == 'bar'
230
+ key.get({:foo => 'bar'})[:foo].should == 'bar'
231
+ end
232
+ end
233
+
234
+ context "for a embedded_document" do
235
+ should "default to nil" do
236
+ key = Key.new(:foo, Address)
237
+ key.get(nil).should be_nil
238
+ end
239
+
240
+ should "return instance if instance" do
241
+ address = Address.new(:city => 'South Bend', :state => 'IN', :zip => 46544)
242
+ key = Key.new(:foo, Address)
243
+ key.get(address).should == address
244
+ end
245
+ end
246
+ end
247
+ end # KeyTest
@@ -0,0 +1,28 @@
1
+ require 'test_helper'
2
+
3
+ class Address; end
4
+
5
+ class MongoMapperTest < Test::Unit::TestCase
6
+ should "be able to write and read connection" do
7
+ conn = XGen::Mongo::Driver::Mongo.new
8
+ MongoMapper.connection = conn
9
+ MongoMapper.connection.should == conn
10
+ end
11
+
12
+ should "default connection to new mongo ruby driver" do
13
+ MongoMapper.connection = nil
14
+ MongoMapper.connection.should be_instance_of(XGen::Mongo::Driver::Mongo)
15
+ end
16
+
17
+ should "be able to write and read default database" do
18
+ MongoMapper.database = DefaultDatabase
19
+ MongoMapper.database.should be_instance_of(XGen::Mongo::Driver::DB)
20
+ MongoMapper.database.name.should == DefaultDatabase
21
+ end
22
+
23
+ should "have document not found error" do
24
+ lambda {
25
+ MongoMapper::DocumentNotFound
26
+ }.should_not raise_error
27
+ end
28
+ end