ramsingla-mongomapper 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. data/.gitignore +7 -0
  2. data/History +30 -0
  3. data/LICENSE +20 -0
  4. data/README.rdoc +39 -0
  5. data/Rakefile +71 -0
  6. data/VERSION +1 -0
  7. data/lib/mongomapper.rb +60 -0
  8. data/lib/mongomapper/associations.rb +69 -0
  9. data/lib/mongomapper/associations/array_proxy.rb +6 -0
  10. data/lib/mongomapper/associations/base.rb +50 -0
  11. data/lib/mongomapper/associations/belongs_to_proxy.rb +26 -0
  12. data/lib/mongomapper/associations/has_many_embedded_proxy.rb +19 -0
  13. data/lib/mongomapper/associations/has_many_proxy.rb +28 -0
  14. data/lib/mongomapper/associations/polymorphic_belongs_to_proxy.rb +31 -0
  15. data/lib/mongomapper/associations/proxy.rb +60 -0
  16. data/lib/mongomapper/callbacks.rb +106 -0
  17. data/lib/mongomapper/document.rb +263 -0
  18. data/lib/mongomapper/embedded_document.rb +295 -0
  19. data/lib/mongomapper/finder_options.rb +81 -0
  20. data/lib/mongomapper/key.rb +82 -0
  21. data/lib/mongomapper/observing.rb +50 -0
  22. data/lib/mongomapper/pagination.rb +52 -0
  23. data/lib/mongomapper/rails_compatibility.rb +23 -0
  24. data/lib/mongomapper/save_with_validation.rb +19 -0
  25. data/lib/mongomapper/serialization.rb +55 -0
  26. data/lib/mongomapper/serializers/json_serializer.rb +77 -0
  27. data/lib/mongomapper/validations.rb +47 -0
  28. data/mongomapper.gemspec +105 -0
  29. data/test/serializers/test_json_serializer.rb +104 -0
  30. data/test/test_associations.rb +211 -0
  31. data/test/test_callbacks.rb +84 -0
  32. data/test/test_document.rb +995 -0
  33. data/test/test_embedded_document.rb +253 -0
  34. data/test/test_finder_options.rb +148 -0
  35. data/test/test_helper.rb +62 -0
  36. data/test/test_key.rb +200 -0
  37. data/test/test_mongomapper.rb +28 -0
  38. data/test/test_observing.rb +101 -0
  39. data/test/test_rails_compatibility.rb +29 -0
  40. data/test/test_serializations.rb +54 -0
  41. data/test/test_validations.rb +409 -0
  42. metadata +156 -0
@@ -0,0 +1,253 @@
1
+ require 'test_helper'
2
+
3
+ class EmbeddedDocumentTest < Test::Unit::TestCase
4
+ context "Including MongoMapper::EmbeddedDocument" do
5
+ setup do
6
+ @klass = Class.new do
7
+ include MongoMapper::EmbeddedDocument
8
+ end
9
+ end
10
+
11
+ should "clear out document default keys" do
12
+ @klass.keys.size.should == 0
13
+ end
14
+ end
15
+
16
+ context "An instance of an embedded document" do
17
+ setup do
18
+ @document = Class.new do
19
+ include MongoMapper::EmbeddedDocument
20
+
21
+ key :name, String
22
+ key :age, Integer
23
+ end
24
+ end
25
+
26
+ context "when initialized" do
27
+ should "accept a hash that sets keys and values" do
28
+ doc = @document.new(:name => 'John', :age => 23)
29
+ doc.attributes.should == {'name' => 'John', 'age' => 23}
30
+ end
31
+
32
+ should "not throw error if initialized with nil" do
33
+ doc = @document.new(nil)
34
+ end
35
+ end
36
+
37
+ context "mass assigning keys" do
38
+ should "update values for keys provided" do
39
+ doc = @document.new(:name => 'foobar', :age => 10)
40
+ doc.attributes = {:name => 'new value', :age => 5}
41
+ doc.attributes[:name].should == 'new value'
42
+ doc.attributes[:age].should == 5
43
+ end
44
+
45
+ should "not update values for keys that were not provided" do
46
+ doc = @document.new(:name => 'foobar', :age => 10)
47
+ doc.attributes = {:name => 'new value'}
48
+ doc.attributes[:name].should == 'new value'
49
+ doc.attributes[:age].should == 10
50
+ end
51
+
52
+ should "ignore keys that do not exist" do
53
+ doc = @document.new(:name => 'foobar', :age => 10)
54
+ doc.attributes = {:name => 'new value', :foobar => 'baz'}
55
+ doc.attributes[:name].should == 'new value'
56
+ doc.attributes[:foobar].should be(nil)
57
+ end
58
+
59
+ should "not ignore keys that have methods defined" do
60
+ @document.class_eval do
61
+ attr_writer :password
62
+
63
+ def passwd
64
+ @password
65
+ end
66
+ end
67
+
68
+ doc = @document.new(:name => 'foobar', :password => 'secret')
69
+ doc.passwd.should == 'secret'
70
+ end
71
+
72
+ should "typecast key values" do
73
+ doc = @document.new(:name => 1234, :age => '21')
74
+ doc.name.should == '1234'
75
+ doc.age.should == 21
76
+ end
77
+ end
78
+
79
+ context "requesting keys" do
80
+ should "default to empty hash" do
81
+ doc = @document.new
82
+ doc.attributes.should == {}
83
+ end
84
+
85
+ should "return all keys that aren't nil" do
86
+ doc = @document.new(:name => 'string', :age => nil)
87
+ doc.attributes.should == {'name' => 'string'}
88
+ end
89
+ end
90
+
91
+ context "key shorcuts" do
92
+ should "be able to read key with []" do
93
+ doc = @document.new(:name => 'string')
94
+ doc[:name].should == 'string'
95
+ end
96
+
97
+ should "be able to write key value with []=" do
98
+ doc = @document.new
99
+ doc[:name] = 'string'
100
+ doc[:name].should == 'string'
101
+ end
102
+ end
103
+
104
+ context "indifferent access" do
105
+ should "be enabled for keys" do
106
+ doc = @document.new(:name => 'string')
107
+ doc.attributes[:name].should == 'string'
108
+ doc.attributes['name'].should == 'string'
109
+ end
110
+ end
111
+
112
+ context "reading an attribute" do
113
+ should "work for defined keys" do
114
+ doc = @document.new(:name => 'string')
115
+ doc.name.should == 'string'
116
+ end
117
+
118
+ should "raise no method error for undefined keys" do
119
+ doc = @document.new
120
+ lambda { doc.fart }.should raise_error(NoMethodError)
121
+ end
122
+
123
+ should "know if reader defined" do
124
+ doc = @document.new
125
+ doc.reader?('name').should be(true)
126
+ doc.reader?(:name).should be(true)
127
+ doc.reader?('age').should be(true)
128
+ doc.reader?(:age).should be(true)
129
+ doc.reader?('foobar').should be(false)
130
+ doc.reader?(:foobar).should be(false)
131
+ end
132
+
133
+ should "be accessible for use in the model" do
134
+ @document.class_eval do
135
+ def name_and_age
136
+ "#{read_attribute(:name)} (#{read_attribute(:age)})"
137
+ end
138
+ end
139
+
140
+ doc = @document.new(:name => 'John', :age => 27)
141
+ doc.name_and_age.should == 'John (27)'
142
+ end
143
+ end
144
+
145
+ context "reading an attribute before typcasting" do
146
+ should "work for defined keys" do
147
+ doc = @document.new(:name => 12)
148
+ doc.name_before_typecast.should == 12
149
+ end
150
+
151
+ should "raise no method error for undefined keys" do
152
+ doc = @document.new
153
+ lambda { doc.foo_before_typecast }.should raise_error(NoMethodError)
154
+ end
155
+
156
+ should "be accessible for use in a document" do
157
+ @document.class_eval do
158
+ def untypcasted_name
159
+ read_attribute_before_typecast(:name)
160
+ end
161
+ end
162
+
163
+ doc = @document.new(:name => 12)
164
+ doc.name.should == '12'
165
+ doc.untypcasted_name.should == 12
166
+ end
167
+ end
168
+
169
+ context "writing an attribute" do
170
+ should "work for defined keys" do
171
+ doc = @document.new
172
+ doc.name = 'John'
173
+ doc.name.should == 'John'
174
+ end
175
+
176
+ should "raise no method error for undefined keys" do
177
+ doc = @document.new
178
+ lambda { doc.fart = 'poof!' }.should raise_error(NoMethodError)
179
+ end
180
+
181
+ should "typecast value" do
182
+ doc = @document.new
183
+ doc.name = 1234
184
+ doc.name.should == '1234'
185
+ doc.age = '21'
186
+ doc.age.should == 21
187
+ end
188
+
189
+ should "know if writer defined" do
190
+ doc = @document.new
191
+ doc.writer?('name').should be(true)
192
+ doc.writer?('name=').should be(true)
193
+ doc.writer?(:name).should be(true)
194
+ doc.writer?('age').should be(true)
195
+ doc.writer?('age=').should be(true)
196
+ doc.writer?(:age).should be(true)
197
+ doc.writer?('foobar').should be(false)
198
+ doc.writer?('foobar=').should be(false)
199
+ doc.writer?(:foobar).should be(false)
200
+ end
201
+
202
+ should "be accessible for use in the model" do
203
+ @document.class_eval do
204
+ def name_and_age=(new_value)
205
+ new_value.match(/([^\(\s]+) \((.*)\)/)
206
+ write_attribute :name, $1
207
+ write_attribute :age, $2
208
+ end
209
+ end
210
+
211
+ doc = @document.new
212
+ doc.name_and_age = 'Frank (62)'
213
+ doc.name.should == 'Frank'
214
+ doc.age.should == 62
215
+ end
216
+ end # writing an attribute
217
+
218
+ context "respond_to?" do
219
+ setup do
220
+ @doc = @document.new
221
+ end
222
+
223
+ should "work for readers" do
224
+ @doc.respond_to?(:name).should be_true
225
+ @doc.respond_to?('name').should be_true
226
+ end
227
+
228
+ should "work for writers" do
229
+ @doc.respond_to?(:name=).should be_true
230
+ @doc.respond_to?('name=').should be_true
231
+ end
232
+
233
+ should "work for readers before typecast" do
234
+ @doc.respond_to?(:name_before_typecast).should be_true
235
+ @doc.respond_to?('name_before_typecast').should be_true
236
+ end
237
+ end
238
+
239
+ context "equality" do
240
+ should "be true if all keys and values are equal" do
241
+ doc1 = @document.new(:name => 'John', :age => 27)
242
+ doc2 = @document.new(:name => 'John', :age => 27)
243
+ doc1.should == doc2
244
+ end
245
+
246
+ should "be false if not all the keys and values are equal" do
247
+ doc1 = @document.new(:name => 'Steve', :age => 27)
248
+ doc2 = @document.new(:name => 'John', :age => 27)
249
+ doc1.should_not == doc2
250
+ end
251
+ end
252
+ end # instance of a embedded document
253
+ end
@@ -0,0 +1,148 @@
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 "work arbitrarily deep" do
51
+ FinderOptions.to_mongo_criteria(:foo => {:bar => [1,2,3]}).should == {
52
+ :foo => {:bar => {'$in' => [1,2,3]}}
53
+ }
54
+ end
55
+ end
56
+
57
+ context "ordering" do
58
+ should "single field with ascending direction" do
59
+ hash = OrderedHash.new
60
+ hash[:foo] = 1
61
+ FinderOptions.to_mongo_options(:order => 'foo asc')[:sort].should == hash
62
+ FinderOptions.to_mongo_options(:order => 'foo ASC')[:sort].should == hash
63
+ end
64
+
65
+ should "single field with descending direction" do
66
+ hash = OrderedHash.new
67
+ hash[:foo] = -1
68
+ FinderOptions.to_mongo_options(:order => 'foo desc')[:sort].should == hash
69
+ FinderOptions.to_mongo_options(:order => 'foo DESC')[:sort].should == hash
70
+ end
71
+
72
+ should "convert field without direction to ascending" do
73
+ hash = OrderedHash.new
74
+ hash[:foo] = 1
75
+ FinderOptions.to_mongo_options(:order => 'foo')[:sort].should == hash
76
+ end
77
+
78
+ should "convert multiple fields with directions" do
79
+ hash = OrderedHash.new
80
+ hash[:foo] = -1
81
+ hash[:bar] = 1
82
+ hash[:baz] = -1
83
+ FinderOptions.to_mongo_options(:order => 'foo desc, bar asc, baz desc')[:sort].should == hash
84
+ end
85
+
86
+ should "convert multiple fields with some missing directions" do
87
+ hash = OrderedHash.new
88
+ hash[:foo] = -1
89
+ hash[:bar] = 1
90
+ hash[:baz] = 1
91
+ FinderOptions.to_mongo_options(:order => 'foo desc, bar, baz')[:sort].should == hash
92
+ end
93
+ end
94
+
95
+ context "offset" do
96
+ should "default to 0" do
97
+ FinderOptions.to_mongo_options({})[:offset].should == 0
98
+ end
99
+
100
+ should "use offset provided" do
101
+ FinderOptions.to_mongo_options(:offset => 2)[:offset].should == 2
102
+ end
103
+
104
+ should "covert string to integer" do
105
+ FinderOptions.to_mongo_options(:offset => '2')[:offset].should == 2
106
+ end
107
+ end
108
+
109
+ context "limit" do
110
+ should "default to 0" do
111
+ FinderOptions.to_mongo_options({})[:limit].should == 0
112
+ end
113
+
114
+ should "use offset provided" do
115
+ FinderOptions.to_mongo_options(:limit => 2)[:limit].should == 2
116
+ end
117
+
118
+ should "covert string to integer" do
119
+ FinderOptions.to_mongo_options(:limit => '2')[:limit].should == 2
120
+ end
121
+ end
122
+
123
+ context "fields" do
124
+ should "default to nil" do
125
+ FinderOptions.to_mongo_options({})[:fields].should be(nil)
126
+ end
127
+
128
+ should "be converted to nil if empty string" do
129
+ FinderOptions.to_mongo_options(:fields => '')[:fields].should be(nil)
130
+ end
131
+
132
+ should "be converted to nil if []" do
133
+ FinderOptions.to_mongo_options(:fields => [])[:fields].should be(nil)
134
+ end
135
+
136
+ should "should work with array" do
137
+ FinderOptions.to_mongo_options({:fields => %w(a b)})[:fields].should == %w(a b)
138
+ end
139
+
140
+ should "convert comma separated list to array" do
141
+ FinderOptions.to_mongo_options({:fields => 'a, b'})[:fields].should == %w(a b)
142
+ end
143
+
144
+ should "also work as select" do
145
+ FinderOptions.new(:select => %w(a b)).options[:fields].should == %w(a b)
146
+ end
147
+ end
148
+ end # FinderOptionsTest
@@ -0,0 +1,62 @@
1
+ require 'pathname'
2
+ require 'rubygems'
3
+ require 'test/unit'
4
+ require 'shoulda'
5
+
6
+ gem 'mocha', '~> 0.9.4'
7
+ gem 'jnunemaker-matchy', '0.4.0'
8
+
9
+ require 'matchy'
10
+ require 'mocha'
11
+
12
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
13
+ dir = (Pathname(__FILE__).dirname + '..' + 'lib').expand_path
14
+ require dir + 'mongomapper'
15
+
16
+ class Test::Unit::TestCase
17
+ custom_matcher :be_nil do |receiver, matcher, args|
18
+ matcher.positive_failure_message = "Expected #{receiver} to be nil but it wasn't"
19
+ matcher.negative_failure_message = "Expected #{receiver} not to be nil but it was"
20
+ receiver.nil?
21
+ end
22
+
23
+ custom_matcher :be_true do |receiver, matcher, args|
24
+ matcher.positive_failure_message = "Expected #{receiver} to be true but it wasn't"
25
+ matcher.negative_failure_message = "Expected #{receiver} not to be true but it was"
26
+ receiver.eql?(true)
27
+ end
28
+
29
+ custom_matcher :be_false do |receiver, matcher, args|
30
+ matcher.positive_failure_message = "Expected #{receiver} to be false but it wasn't"
31
+ matcher.negative_failure_message = "Expected #{receiver} not to be false but it was"
32
+ receiver.eql?(false)
33
+ end
34
+
35
+ custom_matcher :be_valid do |receiver, matcher, args|
36
+ matcher.positive_failure_message = "Expected to be valid but it was invalid #{receiver.errors.inspect}"
37
+ matcher.negative_failure_message = "Expected to be invalid but it was valid #{receiver.errors.inspect}"
38
+ receiver.valid?
39
+ end
40
+
41
+ custom_matcher :have_error_on do |receiver, matcher, args|
42
+ receiver.valid?
43
+ attribute = args[0]
44
+ expected_message = args[1]
45
+
46
+ if expected_message.nil?
47
+ matcher.positive_failure_message = "#{receiver} had no errors on #{attribute}"
48
+ matcher.negative_failure_message = "#{receiver} had errors on #{attribute} #{receiver.errors.inspect}"
49
+ !receiver.errors.on(attribute).blank?
50
+ else
51
+ actual = receiver.errors.on(attribute)
52
+ matcher.positive_failure_message = %Q(Expected error on #{attribute} to be "#{expected_message}" but was "#{actual}")
53
+ matcher.negative_failure_message = %Q(Expected error on #{attribute} not to be "#{expected_message}" but was "#{actual}")
54
+ actual == expected_message
55
+ end
56
+ end
57
+ end
58
+
59
+ DefaultDatabase = 'test' unless defined?(DefaultDatabase)
60
+ AlternateDatabase = 'test2' unless defined?(AlternateDatabase)
61
+
62
+ MongoMapper.database = DefaultDatabase