djsun-mongo_mapper 0.5.5.3 → 0.5.6.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.
- 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
|