djsun-mongo_mapper 0.5.5.3 → 0.5.6.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +3 -0
- data/Rakefile +26 -65
- data/VERSION +1 -1
- data/djsun-mongo_mapper.gemspec +9 -8
- data/lib/mongo_mapper.rb +4 -11
- data/lib/mongo_mapper/associations.rb +0 -10
- data/lib/mongo_mapper/associations/many_documents_proxy.rb +10 -10
- data/lib/mongo_mapper/document.rb +75 -70
- data/lib/mongo_mapper/embedded_document.rb +0 -1
- data/lib/mongo_mapper/finder_options.rb +59 -50
- data/lib/mongo_mapper/serialization.rb +1 -2
- data/lib/mongo_mapper/validations.rb +3 -1
- data/mongo_mapper.gemspec +9 -8
- data/specs.watchr +2 -2
- data/test/functional/associations/test_many_documents_as_proxy.rb +2 -2
- data/test/functional/associations/test_many_polymorphic_proxy.rb +6 -6
- data/test/functional/associations/test_many_proxy.rb +6 -6
- data/test/functional/test_document.rb +153 -50
- data/test/functional/test_pagination.rb +17 -17
- data/test/functional/test_validations.rb +35 -14
- data/test/models.rb +6 -6
- data/test/test_helper.rb +4 -2
- data/test/unit/test_document.rb +2 -6
- data/test/unit/test_embedded_document.rb +2 -6
- data/test/unit/test_finder_options.rb +58 -58
- metadata +5 -5
@@ -1,54 +1,14 @@
|
|
1
1
|
module MongoMapper
|
2
2
|
class FinderOptions
|
3
|
-
attr_reader :options
|
4
|
-
|
5
|
-
def self.to_mongo_criteria(conditions, parent_key=nil)
|
6
|
-
criteria = {}
|
7
|
-
conditions.each_pair do |field, value|
|
8
|
-
field = field_normalized(field)
|
9
|
-
case value
|
10
|
-
when Array
|
11
|
-
operator_present = field.to_s =~ /^\$/
|
12
|
-
criteria[field] = if operator_present
|
13
|
-
value
|
14
|
-
else
|
15
|
-
{'$in' => value}
|
16
|
-
end
|
17
|
-
when Hash
|
18
|
-
criteria[field] = to_mongo_criteria(value, field)
|
19
|
-
else
|
20
|
-
criteria[field] = value
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
criteria
|
25
|
-
end
|
26
|
-
|
27
|
-
def self.to_mongo_options(options)
|
28
|
-
options = options.dup
|
29
|
-
{
|
30
|
-
:fields => to_mongo_fields(options.delete(:fields) || options.delete(:select)),
|
31
|
-
:skip => (options.delete(:skip) || options.delete(:offset) || 0).to_i,
|
32
|
-
:limit => (options.delete(:limit) || 0).to_i,
|
33
|
-
:sort => options.delete(:sort) || to_mongo_sort(options.delete(:order))
|
34
|
-
}
|
35
|
-
end
|
36
|
-
|
37
|
-
def self.field_normalized(field)
|
38
|
-
if field.to_s == 'id'
|
39
|
-
:_id
|
40
|
-
else
|
41
|
-
field
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
3
|
OptionKeys = [:fields, :select, :skip, :offset, :limit, :sort, :order]
|
46
4
|
|
47
|
-
|
5
|
+
attr_reader :model, :options
|
6
|
+
|
7
|
+
def initialize(model, options)
|
48
8
|
raise ArgumentError, "FinderOptions must be a hash" unless options.is_a?(Hash)
|
9
|
+
options.symbolize_keys!
|
49
10
|
|
50
|
-
options = options.
|
51
|
-
@options, @conditions = {}, options.delete(:conditions) || {}
|
11
|
+
@model, @options, @conditions = model, {}, options.delete(:conditions) || {}
|
52
12
|
|
53
13
|
options.each_pair do |key, value|
|
54
14
|
if OptionKeys.include?(key)
|
@@ -60,11 +20,11 @@ module MongoMapper
|
|
60
20
|
end
|
61
21
|
|
62
22
|
def criteria
|
63
|
-
|
23
|
+
to_mongo_criteria(model, @conditions)
|
64
24
|
end
|
65
25
|
|
66
26
|
def options
|
67
|
-
|
27
|
+
to_mongo_options(model, @options)
|
68
28
|
end
|
69
29
|
|
70
30
|
def to_a
|
@@ -72,7 +32,56 @@ module MongoMapper
|
|
72
32
|
end
|
73
33
|
|
74
34
|
private
|
75
|
-
def
|
35
|
+
def to_mongo_criteria(model, conditions, parent_key=nil)
|
36
|
+
criteria = {}
|
37
|
+
add_sci_scope(model, criteria)
|
38
|
+
|
39
|
+
conditions.each_pair do |field, value|
|
40
|
+
field = field_normalized(field)
|
41
|
+
case value
|
42
|
+
when Array
|
43
|
+
operator_present = field.to_s =~ /^\$/
|
44
|
+
criteria[field] = if operator_present
|
45
|
+
value
|
46
|
+
else
|
47
|
+
{'$in' => value}
|
48
|
+
end
|
49
|
+
when Hash
|
50
|
+
criteria[field] = to_mongo_criteria(model, value, field)
|
51
|
+
else
|
52
|
+
criteria[field] = value
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
criteria
|
57
|
+
end
|
58
|
+
|
59
|
+
def field_normalized(field)
|
60
|
+
if field.to_s == 'id'
|
61
|
+
:_id
|
62
|
+
else
|
63
|
+
field
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# adds _type single collection inheritance scope for models that need it
|
68
|
+
def add_sci_scope(model, criteria)
|
69
|
+
if model.single_collection_inherited?
|
70
|
+
criteria[:_type] = model.to_s
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def to_mongo_options(model, options)
|
75
|
+
options = options.dup
|
76
|
+
{
|
77
|
+
:fields => to_mongo_fields(options.delete(:fields) || options.delete(:select)),
|
78
|
+
:skip => (options.delete(:skip) || options.delete(:offset) || 0).to_i,
|
79
|
+
:limit => (options.delete(:limit) || 0).to_i,
|
80
|
+
:sort => options.delete(:sort) || to_mongo_sort(options.delete(:order))
|
81
|
+
}
|
82
|
+
end
|
83
|
+
|
84
|
+
def to_mongo_fields(fields)
|
76
85
|
return if fields.blank?
|
77
86
|
|
78
87
|
if fields.is_a?(String)
|
@@ -82,13 +91,13 @@ module MongoMapper
|
|
82
91
|
end
|
83
92
|
end
|
84
93
|
|
85
|
-
def
|
94
|
+
def to_mongo_sort(sort)
|
86
95
|
return if sort.blank?
|
87
96
|
pieces = sort.split(',')
|
88
97
|
pieces.map { |s| to_mongo_sort_piece(s) }
|
89
98
|
end
|
90
99
|
|
91
|
-
def
|
100
|
+
def to_mongo_sort_piece(str)
|
92
101
|
field, direction = str.strip.split(' ')
|
93
102
|
direction ||= 'ASC'
|
94
103
|
direction = direction.upcase == 'ASC' ? 1 : -1
|
@@ -18,7 +18,9 @@ module MongoMapper
|
|
18
18
|
option :scope
|
19
19
|
|
20
20
|
def valid?(instance)
|
21
|
-
|
21
|
+
value = instance[attribute]
|
22
|
+
return true if allow_blank && value.blank?
|
23
|
+
doc = instance.class.first({self.attribute => value}.merge(scope_conditions(instance)))
|
22
24
|
doc.nil? || instance.id == doc.id
|
23
25
|
end
|
24
26
|
|
data/mongo_mapper.gemspec
CHANGED
@@ -1,16 +1,17 @@
|
|
1
1
|
# Generated by jeweler
|
2
|
-
# DO NOT EDIT THIS FILE
|
3
|
-
# Instead, edit Jeweler::Tasks in Rakefile, and run
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{mongo_mapper}
|
8
|
-
s.version = "0.5.
|
8
|
+
s.version = "0.5.6"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["John Nunemaker"]
|
12
|
-
s.date = %q{2009-10-
|
12
|
+
s.date = %q{2009-10-22}
|
13
13
|
s.default_executable = %q{mmconsole}
|
14
|
+
s.description = %q{Awesome gem for modeling your domain and storing it in mongo}
|
14
15
|
s.email = %q{nunemaker@gmail.com}
|
15
16
|
s.executables = ["mmconsole"]
|
16
17
|
s.extra_rdoc_files = [
|
@@ -94,7 +95,6 @@ Gem::Specification.new do |s|
|
|
94
95
|
s.homepage = %q{http://github.com/jnunemaker/mongomapper}
|
95
96
|
s.rdoc_options = ["--charset=UTF-8"]
|
96
97
|
s.require_paths = ["lib"]
|
97
|
-
s.rubyforge_project = %q{mongomapper}
|
98
98
|
s.rubygems_version = %q{1.3.5}
|
99
99
|
s.summary = %q{Awesome gem for modeling your domain and storing it in mongo}
|
100
100
|
s.test_files = [
|
@@ -143,7 +143,7 @@ Gem::Specification.new do |s|
|
|
143
143
|
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
144
144
|
s.add_runtime_dependency(%q<activesupport>, [">= 2.3"])
|
145
145
|
s.add_runtime_dependency(%q<mongo>, ["= 0.15.1"])
|
146
|
-
s.add_runtime_dependency(%q<jnunemaker-validatable>, ["= 1.
|
146
|
+
s.add_runtime_dependency(%q<jnunemaker-validatable>, ["= 1.8.0"])
|
147
147
|
s.add_development_dependency(%q<jnunemaker-matchy>, ["= 0.4.0"])
|
148
148
|
s.add_development_dependency(%q<shoulda>, ["= 2.10.2"])
|
149
149
|
s.add_development_dependency(%q<timecop>, ["= 0.3.1"])
|
@@ -151,7 +151,7 @@ Gem::Specification.new do |s|
|
|
151
151
|
else
|
152
152
|
s.add_dependency(%q<activesupport>, [">= 2.3"])
|
153
153
|
s.add_dependency(%q<mongo>, ["= 0.15.1"])
|
154
|
-
s.add_dependency(%q<jnunemaker-validatable>, ["= 1.
|
154
|
+
s.add_dependency(%q<jnunemaker-validatable>, ["= 1.8.0"])
|
155
155
|
s.add_dependency(%q<jnunemaker-matchy>, ["= 0.4.0"])
|
156
156
|
s.add_dependency(%q<shoulda>, ["= 2.10.2"])
|
157
157
|
s.add_dependency(%q<timecop>, ["= 0.3.1"])
|
@@ -160,10 +160,11 @@ Gem::Specification.new do |s|
|
|
160
160
|
else
|
161
161
|
s.add_dependency(%q<activesupport>, [">= 2.3"])
|
162
162
|
s.add_dependency(%q<mongo>, ["= 0.15.1"])
|
163
|
-
s.add_dependency(%q<jnunemaker-validatable>, ["= 1.
|
163
|
+
s.add_dependency(%q<jnunemaker-validatable>, ["= 1.8.0"])
|
164
164
|
s.add_dependency(%q<jnunemaker-matchy>, ["= 0.4.0"])
|
165
165
|
s.add_dependency(%q<shoulda>, ["= 2.10.2"])
|
166
166
|
s.add_dependency(%q<timecop>, ["= 0.3.1"])
|
167
167
|
s.add_dependency(%q<mocha>, ["= 0.9.4"])
|
168
168
|
end
|
169
169
|
end
|
170
|
+
|
data/specs.watchr
CHANGED
@@ -4,7 +4,7 @@ def run(cmd)
|
|
4
4
|
end
|
5
5
|
|
6
6
|
def run_test_file(file)
|
7
|
-
run
|
7
|
+
run %Q(ruby -I"lib:test" -rubygems #{file})
|
8
8
|
end
|
9
9
|
|
10
10
|
def run_all_tests
|
@@ -12,7 +12,7 @@ def run_all_tests
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def related_test_files(path)
|
15
|
-
Dir['test/**/*.rb'].select { |file| file =~
|
15
|
+
Dir['test/**/*.rb'].select { |file| file =~ /test_#{File.basename(path)}/ }
|
16
16
|
end
|
17
17
|
|
18
18
|
watch('test/test_helper\.rb') { run_all_tests }
|
@@ -137,7 +137,7 @@ class ManyDocumentsAsProxyTest < Test::Unit::TestCase
|
|
137
137
|
end
|
138
138
|
|
139
139
|
should "work with conditions" do
|
140
|
-
comments = @post.comments.find(:all, :
|
140
|
+
comments = @post.comments.find(:all, :body => 'comment1')
|
141
141
|
comments.should == [@comment1]
|
142
142
|
end
|
143
143
|
|
@@ -154,7 +154,7 @@ class ManyDocumentsAsProxyTest < Test::Unit::TestCase
|
|
154
154
|
end
|
155
155
|
|
156
156
|
should "work with conditions" do
|
157
|
-
comments = @post.comments.all(:
|
157
|
+
comments = @post.comments.all(:body => 'comment1')
|
158
158
|
comments.should == [@comment1]
|
159
159
|
end
|
160
160
|
|
@@ -181,7 +181,7 @@ class ManyPolymorphicProxyTest < Test::Unit::TestCase
|
|
181
181
|
end
|
182
182
|
|
183
183
|
should "work with conditions" do
|
184
|
-
messages = @lounge.messages.find(:all, :
|
184
|
+
messages = @lounge.messages.find(:all, :body => 'Loungin!', :order => "position")
|
185
185
|
messages.should == [@lm1]
|
186
186
|
end
|
187
187
|
|
@@ -197,7 +197,7 @@ class ManyPolymorphicProxyTest < Test::Unit::TestCase
|
|
197
197
|
end
|
198
198
|
|
199
199
|
should "work with conditions" do
|
200
|
-
messages = @lounge.messages.all(:
|
200
|
+
messages = @lounge.messages.all(:body => 'Loungin!', :order => "position")
|
201
201
|
messages.should == [@lm1]
|
202
202
|
end
|
203
203
|
|
@@ -213,7 +213,7 @@ class ManyPolymorphicProxyTest < Test::Unit::TestCase
|
|
213
213
|
end
|
214
214
|
|
215
215
|
should "work with conditions" do
|
216
|
-
message = @lounge.messages.find(:first, :
|
216
|
+
message = @lounge.messages.find(:first, :body => 'I love loungin!', :order => "position asc")
|
217
217
|
message.should == @lm2
|
218
218
|
end
|
219
219
|
end
|
@@ -224,7 +224,7 @@ class ManyPolymorphicProxyTest < Test::Unit::TestCase
|
|
224
224
|
end
|
225
225
|
|
226
226
|
should "work with conditions" do
|
227
|
-
message = @lounge.messages.first(:
|
227
|
+
message = @lounge.messages.first(:body => 'I love loungin!', :order => "position asc")
|
228
228
|
message.should == @lm2
|
229
229
|
end
|
230
230
|
end
|
@@ -235,7 +235,7 @@ class ManyPolymorphicProxyTest < Test::Unit::TestCase
|
|
235
235
|
end
|
236
236
|
|
237
237
|
should "work with conditions" do
|
238
|
-
message = @lounge.messages.find(:last, :
|
238
|
+
message = @lounge.messages.find(:last, :body => 'Loungin!', :order => "position asc")
|
239
239
|
message.should == @lm1
|
240
240
|
end
|
241
241
|
end
|
@@ -246,7 +246,7 @@ class ManyPolymorphicProxyTest < Test::Unit::TestCase
|
|
246
246
|
end
|
247
247
|
|
248
248
|
should "work with conditions" do
|
249
|
-
message = @lounge.messages.last(:
|
249
|
+
message = @lounge.messages.last(:body => 'Loungin!', :order => "position asc")
|
250
250
|
message.should == @lm1
|
251
251
|
end
|
252
252
|
end
|
@@ -215,7 +215,7 @@ class ManyProxyTest < Test::Unit::TestCase
|
|
215
215
|
end
|
216
216
|
|
217
217
|
should "work with conditions" do
|
218
|
-
statuses = @project1.statuses.find(:all, :
|
218
|
+
statuses = @project1.statuses.find(:all, :name => 'Complete')
|
219
219
|
statuses.should == [@complete]
|
220
220
|
end
|
221
221
|
|
@@ -231,7 +231,7 @@ class ManyProxyTest < Test::Unit::TestCase
|
|
231
231
|
end
|
232
232
|
|
233
233
|
should "work with conditions" do
|
234
|
-
statuses = @project1.statuses.all(:
|
234
|
+
statuses = @project1.statuses.all(:name => 'Complete')
|
235
235
|
statuses.should == [@complete]
|
236
236
|
end
|
237
237
|
|
@@ -247,7 +247,7 @@ class ManyProxyTest < Test::Unit::TestCase
|
|
247
247
|
end
|
248
248
|
|
249
249
|
should "work with conditions" do
|
250
|
-
status = @project1.statuses.find(:first, :
|
250
|
+
status = @project1.statuses.find(:first, :name => 'Complete')
|
251
251
|
status.should == @complete
|
252
252
|
end
|
253
253
|
end
|
@@ -258,7 +258,7 @@ class ManyProxyTest < Test::Unit::TestCase
|
|
258
258
|
end
|
259
259
|
|
260
260
|
should "work with conditions" do
|
261
|
-
status = @project1.statuses.first(:
|
261
|
+
status = @project1.statuses.first(:name => 'Complete')
|
262
262
|
status.should == @complete
|
263
263
|
end
|
264
264
|
end
|
@@ -269,7 +269,7 @@ class ManyProxyTest < Test::Unit::TestCase
|
|
269
269
|
end
|
270
270
|
|
271
271
|
should "work with conditions" do
|
272
|
-
status = @project1.statuses.find(:last, :order => 'position', :
|
272
|
+
status = @project1.statuses.find(:last, :order => 'position', :name => 'New')
|
273
273
|
status.should == @brand_new
|
274
274
|
end
|
275
275
|
end
|
@@ -280,7 +280,7 @@ class ManyProxyTest < Test::Unit::TestCase
|
|
280
280
|
end
|
281
281
|
|
282
282
|
should "work with conditions" do
|
283
|
-
status = @project1.statuses.last(:order => 'position', :
|
283
|
+
status = @project1.statuses.last(:order => 'position', :name => 'New')
|
284
284
|
status.should == @brand_new
|
285
285
|
end
|
286
286
|
end
|
@@ -24,7 +24,7 @@ class DocumentTest < Test::Unit::TestCase
|
|
24
24
|
doc.using_custom_id?.should be_false
|
25
25
|
end
|
26
26
|
end
|
27
|
-
|
27
|
+
|
28
28
|
context "Saving a document with a blank binary value" do
|
29
29
|
setup do
|
30
30
|
@document.key :file, Binary
|
@@ -41,9 +41,9 @@ class DocumentTest < Test::Unit::TestCase
|
|
41
41
|
@id = Mongo::ObjectID.new.to_s
|
42
42
|
@document.collection.insert({
|
43
43
|
:_id => @id,
|
44
|
-
:first_name => 'John',
|
45
|
-
:last_name => 'Nunemaker',
|
46
|
-
:age => 27,
|
44
|
+
:first_name => 'John',
|
45
|
+
:last_name => 'Nunemaker',
|
46
|
+
:age => 27,
|
47
47
|
:favorite_color => 'red',
|
48
48
|
:skills => ['ruby', 'rails', 'javascript', 'xhtml', 'css']
|
49
49
|
})
|
@@ -58,7 +58,7 @@ class DocumentTest < Test::Unit::TestCase
|
|
58
58
|
doc.skills.should == ['ruby', 'rails', 'javascript', 'xhtml', 'css']
|
59
59
|
end
|
60
60
|
end
|
61
|
-
|
61
|
+
|
62
62
|
context "Document Class Methods" do
|
63
63
|
context "Using key with type Array" do
|
64
64
|
setup do
|
@@ -141,7 +141,7 @@ class DocumentTest < Test::Unit::TestCase
|
|
141
141
|
doc.foo['baz'].should == 'bar'
|
142
142
|
end
|
143
143
|
end
|
144
|
-
|
144
|
+
|
145
145
|
context "Using key with custom type with default" do
|
146
146
|
setup do
|
147
147
|
@document.key :window, WindowSize, :default => WindowSize.new(600, 480)
|
@@ -150,19 +150,19 @@ class DocumentTest < Test::Unit::TestCase
|
|
150
150
|
should "default to default" do
|
151
151
|
doc = @document.new
|
152
152
|
doc.window.should == WindowSize.new(600, 480)
|
153
|
-
|
153
|
+
|
154
154
|
end
|
155
|
-
|
155
|
+
|
156
156
|
should "save and load from mongo" do
|
157
157
|
doc = @document.new
|
158
158
|
doc.save
|
159
|
-
|
159
|
+
|
160
160
|
from_db = @document.find(doc.id)
|
161
161
|
from_db.window.should == WindowSize.new(600, 480)
|
162
162
|
end
|
163
163
|
end
|
164
|
-
|
165
|
-
|
164
|
+
|
165
|
+
|
166
166
|
context "Creating a single document" do
|
167
167
|
setup do
|
168
168
|
@doc_instance = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
|
@@ -299,7 +299,9 @@ class DocumentTest < Test::Unit::TestCase
|
|
299
299
|
end
|
300
300
|
|
301
301
|
should "raise error if document not found" do
|
302
|
-
lambda {
|
302
|
+
lambda {
|
303
|
+
@document.find(123)
|
304
|
+
}.should raise_error(MongoMapper::DocumentNotFound)
|
303
305
|
end
|
304
306
|
end
|
305
307
|
|
@@ -311,31 +313,31 @@ class DocumentTest < Test::Unit::TestCase
|
|
311
313
|
should "work as array" do
|
312
314
|
@document.find([@doc1.id, @doc2.id]).should == [@doc1, @doc2]
|
313
315
|
end
|
314
|
-
|
316
|
+
|
315
317
|
should "return array if array only has one element" do
|
316
318
|
@document.find([@doc1.id]).should == [@doc1]
|
317
319
|
end
|
318
320
|
end
|
319
|
-
|
321
|
+
|
320
322
|
should "be able to find using condition auto-detection" do
|
321
323
|
@document.first(:first_name => 'John').should == @doc1
|
322
324
|
@document.all(:last_name => 'Nunemaker', :order => 'age desc').should == [@doc1, @doc3]
|
323
325
|
end
|
324
|
-
|
326
|
+
|
325
327
|
context "with :all" do
|
326
328
|
should "find all documents" do
|
327
329
|
@document.find(:all, :order => 'first_name').should == [@doc1, @doc3, @doc2]
|
328
330
|
end
|
329
331
|
|
330
332
|
should "be able to add conditions" do
|
331
|
-
@document.find(:all, :
|
333
|
+
@document.find(:all, :first_name => 'John').should == [@doc1]
|
332
334
|
end
|
333
335
|
end
|
334
336
|
|
335
337
|
context "with #all" do
|
336
338
|
should "find all documents based on criteria" do
|
337
339
|
@document.all(:order => 'first_name').should == [@doc1, @doc3, @doc2]
|
338
|
-
@document.all(:
|
340
|
+
@document.all(:last_name => 'Nunemaker', :order => 'age desc').should == [@doc1, @doc3]
|
339
341
|
end
|
340
342
|
end
|
341
343
|
|
@@ -348,7 +350,7 @@ class DocumentTest < Test::Unit::TestCase
|
|
348
350
|
context "with #first" do
|
349
351
|
should "find first document based on criteria" do
|
350
352
|
@document.first(:order => 'first_name').should == @doc1
|
351
|
-
@document.first(:
|
353
|
+
@document.first(:age => 28).should == @doc2
|
352
354
|
end
|
353
355
|
end
|
354
356
|
|
@@ -361,13 +363,13 @@ class DocumentTest < Test::Unit::TestCase
|
|
361
363
|
context "with #last" do
|
362
364
|
should "find last document based on criteria" do
|
363
365
|
@document.last(:order => 'age').should == @doc2
|
364
|
-
@document.last(:order => 'age', :
|
366
|
+
@document.last(:order => 'age', :age => 28).should == @doc2
|
365
367
|
end
|
366
|
-
|
368
|
+
|
367
369
|
should "raise error if no order provided" do
|
368
370
|
lambda { @document.last() }.should raise_error
|
369
371
|
end
|
370
|
-
end
|
372
|
+
end
|
371
373
|
|
372
374
|
context "with :find_by" do
|
373
375
|
should "find document based on argument" do
|
@@ -669,11 +671,11 @@ class DocumentTest < Test::Unit::TestCase
|
|
669
671
|
@thing.properties << @property3
|
670
672
|
end
|
671
673
|
|
672
|
-
|
674
|
+
should "not execute on a belongs_to association" do
|
673
675
|
Thing.count.should == 1
|
674
676
|
@property1.destroy
|
675
|
-
Thing.count.should ==
|
676
|
-
@property1.
|
677
|
+
Thing.count.should == 1
|
678
|
+
@property1.should be_frozen
|
677
679
|
end
|
678
680
|
end
|
679
681
|
end
|
@@ -722,14 +724,14 @@ class DocumentTest < Test::Unit::TestCase
|
|
722
724
|
should "allow creating index for a key" do
|
723
725
|
@document.ensure_index :first_name
|
724
726
|
MongoMapper.ensure_indexes!
|
725
|
-
|
726
|
-
@document.should have_index('first_name_1')
|
727
|
+
|
728
|
+
@document.should have_index('first_name_1')
|
727
729
|
end
|
728
730
|
|
729
731
|
should "allow creating unique index for a key" do
|
730
732
|
@document.ensure_index :first_name, :unique => true
|
731
733
|
MongoMapper.ensure_indexes!
|
732
|
-
|
734
|
+
|
733
735
|
@document.should have_index('first_name_1')
|
734
736
|
end
|
735
737
|
|
@@ -737,13 +739,19 @@ class DocumentTest < Test::Unit::TestCase
|
|
737
739
|
@document.ensure_index [[:first_name, 1], [:last_name, -1]]
|
738
740
|
MongoMapper.ensure_indexes!
|
739
741
|
|
740
|
-
|
742
|
+
# order is different for different versions of ruby so instead of
|
743
|
+
# just checking have_index('first_name_1_last_name_-1') I'm checking
|
744
|
+
# the values of the indexes to make sure the index creation was successful
|
745
|
+
@document.collection.index_information.detect do |index|
|
746
|
+
keys = index[1]
|
747
|
+
keys.include?(['first_name', 1]) && keys.include?(['last_name', -1])
|
748
|
+
end.should_not be_nil
|
741
749
|
end
|
742
750
|
|
743
751
|
should "work with :index shortcut when defining key" do
|
744
752
|
@document.key :father, String, :index => true
|
745
753
|
MongoMapper.ensure_indexes!
|
746
|
-
|
754
|
+
|
747
755
|
@document.should have_index('father_1')
|
748
756
|
end
|
749
757
|
end
|
@@ -794,7 +802,7 @@ class DocumentTest < Test::Unit::TestCase
|
|
794
802
|
from_db = RealPerson.find(person.id)
|
795
803
|
from_db.name.should == "David"
|
796
804
|
end
|
797
|
-
|
805
|
+
|
798
806
|
context "with key of type date" do
|
799
807
|
should "save the date value as a Time object" do
|
800
808
|
doc = @document.new(:first_name => 'John', :age => '27', :date => "12/01/2009")
|
@@ -891,16 +899,16 @@ class DocumentTest < Test::Unit::TestCase
|
|
891
899
|
from_db.age.should == 30
|
892
900
|
end
|
893
901
|
end
|
894
|
-
|
902
|
+
|
895
903
|
context "update_attributes" do
|
896
904
|
setup do
|
897
905
|
@document.key :foo, String, :required => true
|
898
906
|
end
|
899
|
-
|
907
|
+
|
900
908
|
should "return true if document valid" do
|
901
909
|
@document.new.update_attributes(:foo => 'bar').should be_true
|
902
910
|
end
|
903
|
-
|
911
|
+
|
904
912
|
should "return false if document not valid" do
|
905
913
|
@document.new.update_attributes({}).should be_false
|
906
914
|
end
|
@@ -941,63 +949,158 @@ class DocumentTest < Test::Unit::TestCase
|
|
941
949
|
end
|
942
950
|
end
|
943
951
|
end
|
944
|
-
|
952
|
+
|
945
953
|
context "Single collection inheritance" do
|
946
954
|
setup do
|
947
955
|
class ::DocParent
|
948
956
|
include MongoMapper::Document
|
949
957
|
key :_type, String
|
958
|
+
key :name, String
|
950
959
|
end
|
951
|
-
|
952
|
-
class ::DocChild < ::DocParent; end
|
953
960
|
DocParent.collection.clear
|
954
961
|
|
962
|
+
class ::DocDaughter < ::DocParent; end
|
963
|
+
class ::DocSon < ::DocParent; end
|
964
|
+
class ::DocGrandSon < ::DocSon; end
|
965
|
+
|
955
966
|
@parent = DocParent.new({:name => "Daddy Warbucks"})
|
956
|
-
@
|
967
|
+
@daughter = DocDaughter.new({:name => "Little Orphan Annie"})
|
957
968
|
end
|
958
969
|
|
959
970
|
teardown do
|
960
|
-
Object.send :remove_const, 'DocParent'
|
961
|
-
Object.send :remove_const, '
|
971
|
+
Object.send :remove_const, 'DocParent' if defined?(::DocParent)
|
972
|
+
Object.send :remove_const, 'DocDaughter' if defined?(::DocDaughter)
|
973
|
+
Object.send :remove_const, 'DocSon' if defined?(::DocSon)
|
974
|
+
Object.send :remove_const, 'DocGrandSon' if defined?(::DocGrandSon)
|
962
975
|
end
|
963
976
|
|
964
977
|
should "use the same collection in the subclass" do
|
965
|
-
|
978
|
+
DocDaughter.collection.name.should == DocParent.collection.name
|
966
979
|
end
|
967
980
|
|
968
981
|
should "assign the class name into the _type property" do
|
969
982
|
@parent._type.should == 'DocParent'
|
970
|
-
@
|
983
|
+
@daughter._type.should == 'DocDaughter'
|
971
984
|
end
|
972
985
|
|
973
986
|
should "load the document with the assigned type" do
|
974
987
|
@parent.save
|
975
|
-
@
|
976
|
-
|
988
|
+
@daughter.save
|
989
|
+
|
977
990
|
collection = DocParent.find(:all)
|
978
991
|
collection.size.should == 2
|
979
992
|
collection.first.should be_kind_of(DocParent)
|
980
993
|
collection.first.name.should == "Daddy Warbucks"
|
981
|
-
collection.last.should be_kind_of(
|
994
|
+
collection.last.should be_kind_of(DocDaughter)
|
982
995
|
collection.last.name.should == "Little Orphan Annie"
|
983
996
|
end
|
984
|
-
|
997
|
+
|
985
998
|
should "gracefully handle when the type can't be constantized" do
|
986
999
|
doc = DocParent.new(:name => 'Nunes')
|
987
1000
|
doc._type = 'FoobarBaz'
|
988
1001
|
doc.save
|
989
|
-
|
1002
|
+
|
990
1003
|
collection = DocParent.all
|
991
1004
|
collection.last.should == doc
|
992
1005
|
collection.last.should be_kind_of(DocParent)
|
993
1006
|
end
|
1007
|
+
|
1008
|
+
should "find scoped to class" do
|
1009
|
+
john = DocSon.create(:name => 'John')
|
1010
|
+
steve = DocSon.create(:name => 'Steve')
|
1011
|
+
steph = DocDaughter.create(:name => 'Steph')
|
1012
|
+
carrie = DocDaughter.create(:name => 'Carrie')
|
1013
|
+
|
1014
|
+
DocGrandSon.all(:order => 'name').should == []
|
1015
|
+
DocSon.all(:order => 'name').should == [john, steve]
|
1016
|
+
DocDaughter.all(:order => 'name').should == [carrie, steph]
|
1017
|
+
DocParent.all(:order => 'name').should == [carrie, john, steph, steve]
|
1018
|
+
end
|
1019
|
+
|
1020
|
+
should "raise error if not found scoped to class" do
|
1021
|
+
john = DocSon.create(:name => 'John')
|
1022
|
+
steph = DocDaughter.create(:name => 'Steph')
|
1023
|
+
|
1024
|
+
lambda {
|
1025
|
+
DocSon.find(steph.id)
|
1026
|
+
}.should raise_error(MongoMapper::DocumentNotFound)
|
1027
|
+
end
|
1028
|
+
|
1029
|
+
should "not raise error for find with parent" do
|
1030
|
+
john = DocSon.create(:name => 'John')
|
1031
|
+
|
1032
|
+
DocParent.find(john.id).should == john
|
1033
|
+
end
|
1034
|
+
|
1035
|
+
should "count scoped to class" do
|
1036
|
+
john = DocSon.create(:name => 'John')
|
1037
|
+
steve = DocSon.create(:name => 'Steve')
|
1038
|
+
steph = DocDaughter.create(:name => 'Steph')
|
1039
|
+
carrie = DocDaughter.create(:name => 'Carrie')
|
1040
|
+
|
1041
|
+
DocGrandSon.count.should == 0
|
1042
|
+
DocSon.count.should == 2
|
1043
|
+
DocDaughter.count.should == 2
|
1044
|
+
DocParent.count.should == 4
|
1045
|
+
end
|
1046
|
+
|
1047
|
+
should "know if it is single_collection_inherited?" do
|
1048
|
+
DocParent.single_collection_inherited?.should be_false
|
1049
|
+
|
1050
|
+
DocDaughter.single_collection_inherited?.should be_true
|
1051
|
+
DocSon.single_collection_inherited?.should be_true
|
1052
|
+
end
|
1053
|
+
|
1054
|
+
should "know if single_collection_inherited_superclass?" do
|
1055
|
+
DocParent.single_collection_inherited_superclass?.should be_false
|
1056
|
+
|
1057
|
+
DocDaughter.single_collection_inherited_superclass?.should be_true
|
1058
|
+
DocSon.single_collection_inherited_superclass?.should be_true
|
1059
|
+
DocGrandSon.single_collection_inherited_superclass?.should be_true
|
1060
|
+
end
|
1061
|
+
|
1062
|
+
should "not be able to destroy each other" do
|
1063
|
+
john = DocSon.create(:name => 'John')
|
1064
|
+
steph = DocDaughter.create(:name => 'Steph')
|
1065
|
+
|
1066
|
+
lambda {
|
1067
|
+
DocSon.destroy(steph.id)
|
1068
|
+
}.should raise_error(MongoMapper::DocumentNotFound)
|
1069
|
+
end
|
1070
|
+
|
1071
|
+
should "not be able to delete each other" do
|
1072
|
+
john = DocSon.create(:name => 'John')
|
1073
|
+
steph = DocDaughter.create(:name => 'Steph')
|
1074
|
+
|
1075
|
+
lambda {
|
1076
|
+
DocSon.delete(steph.id)
|
1077
|
+
}.should_not change { DocParent.count }
|
1078
|
+
end
|
1079
|
+
|
1080
|
+
should "be able to destroy using parent" do
|
1081
|
+
john = DocSon.create(:name => 'John')
|
1082
|
+
steph = DocDaughter.create(:name => 'Steph')
|
1083
|
+
|
1084
|
+
lambda {
|
1085
|
+
DocParent.destroy_all
|
1086
|
+
}.should change { DocParent.count }.by(-2)
|
1087
|
+
end
|
1088
|
+
|
1089
|
+
should "be able to delete using parent" do
|
1090
|
+
john = DocSon.create(:name => 'John')
|
1091
|
+
steph = DocDaughter.create(:name => 'Steph')
|
1092
|
+
|
1093
|
+
lambda {
|
1094
|
+
DocParent.delete_all
|
1095
|
+
}.should change { DocParent.count }.by(-2)
|
1096
|
+
end
|
994
1097
|
end
|
995
1098
|
|
996
1099
|
context "timestamping" do
|
997
1100
|
setup do
|
998
1101
|
@document.timestamps!
|
999
1102
|
end
|
1000
|
-
|
1103
|
+
|
1001
1104
|
should "set created_at and updated_at on create" do
|
1002
1105
|
doc = @document.new(:first_name => 'John', :age => 27)
|
1003
1106
|
doc.created_at.should be(nil)
|
@@ -1012,11 +1115,11 @@ class DocumentTest < Test::Unit::TestCase
|
|
1012
1115
|
old_created_at = doc.created_at
|
1013
1116
|
old_updated_at = doc.updated_at
|
1014
1117
|
doc.first_name = 'Johnny'
|
1015
|
-
|
1118
|
+
|
1016
1119
|
Timecop.freeze(Time.now + 5.seconds) do
|
1017
1120
|
doc.save
|
1018
1121
|
end
|
1019
|
-
|
1122
|
+
|
1020
1123
|
doc.created_at.should == old_created_at
|
1021
1124
|
doc.updated_at.should_not == old_updated_at
|
1022
1125
|
end
|
@@ -1025,7 +1128,7 @@ class DocumentTest < Test::Unit::TestCase
|
|
1025
1128
|
doc = @document.create(:first_name => 'John', :age => 27)
|
1026
1129
|
old_created_at = doc.created_at
|
1027
1130
|
old_updated_at = doc.updated_at
|
1028
|
-
|
1131
|
+
|
1029
1132
|
Timecop.freeze(Time.now + 5.seconds) do
|
1030
1133
|
@document.update(doc._id, { :first_name => 'Johnny' })
|
1031
1134
|
end
|