mongo_mapper 0.7.6 → 0.8.0
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 +4 -8
- data/bin/mmconsole +1 -1
- data/examples/keys.rb +37 -0
- data/examples/plugins.rb +41 -0
- data/examples/querying.rb +35 -0
- data/examples/scopes.rb +52 -0
- data/lib/mongo_mapper.rb +77 -97
- data/lib/mongo_mapper/connection.rb +83 -0
- data/lib/mongo_mapper/document.rb +10 -252
- data/lib/mongo_mapper/embedded_document.rb +7 -46
- data/lib/mongo_mapper/exceptions.rb +30 -0
- data/lib/mongo_mapper/extensions/array.rb +19 -0
- data/lib/mongo_mapper/extensions/binary.rb +22 -0
- data/lib/mongo_mapper/extensions/boolean.rb +44 -0
- data/lib/mongo_mapper/extensions/date.rb +25 -0
- data/lib/mongo_mapper/extensions/float.rb +14 -0
- data/lib/mongo_mapper/extensions/hash.rb +14 -0
- data/lib/mongo_mapper/extensions/integer.rb +19 -0
- data/lib/mongo_mapper/extensions/kernel.rb +9 -0
- data/lib/mongo_mapper/extensions/nil_class.rb +18 -0
- data/lib/mongo_mapper/extensions/object.rb +27 -0
- data/lib/mongo_mapper/extensions/object_id.rb +30 -0
- data/lib/mongo_mapper/extensions/set.rb +20 -0
- data/lib/mongo_mapper/extensions/string.rb +18 -0
- data/lib/mongo_mapper/extensions/time.rb +29 -0
- data/lib/mongo_mapper/plugins.rb +1 -21
- data/lib/mongo_mapper/plugins/accessible.rb +44 -0
- data/lib/mongo_mapper/plugins/associations.rb +7 -24
- data/lib/mongo_mapper/plugins/associations/base.rb +1 -0
- data/lib/mongo_mapper/plugins/associations/belongs_to_polymorphic_proxy.rb +5 -6
- data/lib/mongo_mapper/plugins/associations/belongs_to_proxy.rb +5 -6
- data/lib/mongo_mapper/plugins/associations/collection.rb +1 -0
- data/lib/mongo_mapper/plugins/associations/embedded_collection.rb +2 -1
- data/lib/mongo_mapper/plugins/associations/in_array_proxy.rb +22 -39
- data/lib/mongo_mapper/plugins/associations/many_documents_as_proxy.rb +4 -4
- data/lib/mongo_mapper/plugins/associations/many_documents_proxy.rb +22 -23
- data/lib/mongo_mapper/plugins/associations/many_embedded_polymorphic_proxy.rb +1 -0
- data/lib/mongo_mapper/plugins/associations/many_embedded_proxy.rb +1 -0
- data/lib/mongo_mapper/plugins/associations/many_polymorphic_proxy.rb +1 -0
- data/lib/mongo_mapper/plugins/associations/one_embedded_proxy.rb +2 -3
- data/lib/mongo_mapper/plugins/associations/one_proxy.rb +6 -7
- data/lib/mongo_mapper/plugins/associations/proxy.rb +8 -6
- data/lib/mongo_mapper/plugins/caching.rb +21 -0
- data/lib/mongo_mapper/plugins/callbacks.rb +4 -3
- data/lib/mongo_mapper/plugins/clone.rb +10 -4
- data/lib/mongo_mapper/plugins/descendants.rb +1 -0
- data/lib/mongo_mapper/plugins/dirty.rb +1 -0
- data/lib/mongo_mapper/plugins/document.rb +41 -0
- data/lib/mongo_mapper/plugins/dynamic_querying.rb +41 -0
- data/lib/mongo_mapper/{support/find.rb → plugins/dynamic_querying/dynamic_finder.rb} +3 -36
- data/lib/mongo_mapper/plugins/embedded_document.rb +49 -0
- data/lib/mongo_mapper/plugins/equality.rb +3 -9
- data/lib/mongo_mapper/plugins/identity_map.rb +8 -10
- data/lib/mongo_mapper/plugins/indexes.rb +12 -0
- data/lib/mongo_mapper/plugins/inspect.rb +1 -0
- data/lib/mongo_mapper/plugins/keys.rb +15 -27
- data/lib/mongo_mapper/plugins/keys/key.rb +14 -3
- data/lib/mongo_mapper/plugins/logger.rb +1 -0
- data/lib/mongo_mapper/plugins/modifiers.rb +3 -2
- data/lib/mongo_mapper/plugins/pagination.rb +5 -15
- data/lib/mongo_mapper/plugins/persistence.rb +12 -11
- data/lib/mongo_mapper/plugins/protected.rb +8 -0
- data/lib/mongo_mapper/plugins/querying.rb +236 -0
- data/lib/mongo_mapper/plugins/querying/decorator.rb +46 -0
- data/lib/mongo_mapper/plugins/rails.rb +1 -0
- data/lib/mongo_mapper/plugins/safe.rb +28 -0
- data/lib/mongo_mapper/plugins/sci.rb +32 -0
- data/lib/mongo_mapper/plugins/scopes.rb +21 -0
- data/lib/mongo_mapper/plugins/serialization.rb +1 -0
- data/lib/mongo_mapper/plugins/timestamps.rb +1 -0
- data/lib/mongo_mapper/plugins/userstamps.rb +1 -0
- data/lib/mongo_mapper/plugins/validations.rb +5 -1
- data/lib/mongo_mapper/support/descendant_appends.rb +5 -6
- data/lib/mongo_mapper/version.rb +2 -1
- data/test/NOTE_ON_TESTING +1 -0
- data/test/active_model_lint_test.rb +13 -0
- data/test/functional/associations/test_belongs_to_polymorphic_proxy.rb +63 -0
- data/test/functional/associations/test_belongs_to_proxy.rb +93 -0
- data/test/functional/associations/test_in_array_proxy.rb +319 -0
- data/test/functional/associations/test_many_documents_as_proxy.rb +229 -0
- data/test/functional/associations/test_many_documents_proxy.rb +536 -0
- data/test/functional/associations/test_many_embedded_polymorphic_proxy.rb +176 -0
- data/test/functional/associations/test_many_embedded_proxy.rb +256 -0
- data/test/functional/associations/test_many_polymorphic_proxy.rb +302 -0
- data/test/functional/associations/test_one_embedded_proxy.rb +58 -0
- data/test/functional/associations/test_one_proxy.rb +182 -0
- data/test/functional/test_accessible.rb +168 -0
- data/test/functional/test_associations.rb +44 -0
- data/test/functional/test_binary.rb +27 -0
- data/test/functional/test_caching.rb +76 -0
- data/test/functional/test_callbacks.rb +151 -0
- data/test/functional/test_dirty.rb +163 -0
- data/test/functional/test_document.rb +253 -0
- data/test/functional/test_dynamic_querying.rb +75 -0
- data/test/functional/test_embedded_document.rb +210 -0
- data/test/functional/test_identity_map.rb +506 -0
- data/test/functional/test_indexes.rb +42 -0
- data/test/functional/test_logger.rb +20 -0
- data/test/functional/test_modifiers.rb +416 -0
- data/test/functional/test_pagination.rb +91 -0
- data/test/functional/test_protected.rb +175 -0
- data/test/functional/test_querying.rb +873 -0
- data/test/functional/test_safe.rb +76 -0
- data/test/functional/test_sci.rb +230 -0
- data/test/functional/test_scopes.rb +171 -0
- data/test/functional/test_string_id_compatibility.rb +67 -0
- data/test/functional/test_timestamps.rb +62 -0
- data/test/functional/test_userstamps.rb +27 -0
- data/test/functional/test_validations.rb +342 -0
- data/test/models.rb +227 -0
- data/test/test_helper.rb +98 -0
- data/test/unit/associations/test_base.rb +212 -0
- data/test/unit/associations/test_proxy.rb +105 -0
- data/test/unit/serializers/test_json_serializer.rb +202 -0
- data/test/unit/test_clone.rb +69 -0
- data/test/unit/test_descendant_appends.rb +71 -0
- data/test/unit/test_document.rb +213 -0
- data/test/unit/test_dynamic_finder.rb +125 -0
- data/test/unit/test_embedded_document.rb +644 -0
- data/test/unit/test_extensions.rb +380 -0
- data/test/unit/test_key.rb +185 -0
- data/test/unit/test_keys.rb +55 -0
- data/test/unit/test_mongo_mapper.rb +110 -0
- data/test/unit/test_pagination.rb +11 -0
- data/test/unit/test_plugins.rb +50 -0
- data/test/unit/test_rails.rb +181 -0
- data/test/unit/test_rails_compatibility.rb +52 -0
- data/test/unit/test_serialization.rb +51 -0
- data/test/unit/test_time_zones.rb +39 -0
- data/test/unit/test_validations.rb +544 -0
- metadata +113 -44
- data/lib/mongo_mapper/plugins/pagination/proxy.rb +0 -72
- data/lib/mongo_mapper/query.rb +0 -23
- data/lib/mongo_mapper/support.rb +0 -196
@@ -0,0 +1,91 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class PaginationTest < Test::Unit::TestCase
|
4
|
+
context "Paginating" do
|
5
|
+
setup do
|
6
|
+
@document = Doc do
|
7
|
+
key :first_name, String
|
8
|
+
key :last_name, String
|
9
|
+
key :age, Integer
|
10
|
+
|
11
|
+
def self.per_page; 1 end
|
12
|
+
end
|
13
|
+
|
14
|
+
@doc1 = @document.create(:first_name => 'John', :last_name => 'Nunemaker', :age => '27')
|
15
|
+
@doc2 = @document.create(:first_name => 'Steve', :last_name => 'Smith', :age => '28')
|
16
|
+
@doc3 = @document.create(:first_name => 'Steph', :last_name => 'Nunemaker', :age => '26')
|
17
|
+
end
|
18
|
+
|
19
|
+
should "return the total pages" do
|
20
|
+
result = @document.paginate(:per_page => 2, :page => 1)
|
21
|
+
result.total_pages.should == 2
|
22
|
+
end
|
23
|
+
|
24
|
+
should "return the total pages when defaulting to the document class per_page" do
|
25
|
+
result = @document.paginate(:page => 1)
|
26
|
+
result.total_pages.should == 3
|
27
|
+
end
|
28
|
+
|
29
|
+
should "return the total of records" do
|
30
|
+
result = @document.paginate(:per_page => 2, :page => 1)
|
31
|
+
result.total_entries.should == 3
|
32
|
+
end
|
33
|
+
|
34
|
+
should "return the items" do
|
35
|
+
result = @document.paginate(:per_page => 2, :page => 1, :order => 'first_name')
|
36
|
+
result.size.should == 2
|
37
|
+
result.should == [@doc1, @doc3]
|
38
|
+
end
|
39
|
+
|
40
|
+
should "accept conditions" do
|
41
|
+
result = @document.paginate({
|
42
|
+
:last_name => 'Nunemaker',
|
43
|
+
:order => "age DESC",
|
44
|
+
:per_page => 2,
|
45
|
+
:page => 1,
|
46
|
+
})
|
47
|
+
result.should == [@doc1, @doc3]
|
48
|
+
result.first.age.should == 27
|
49
|
+
|
50
|
+
result = @document.paginate({
|
51
|
+
:conditions => {:last_name => 'Nunemaker'},
|
52
|
+
:order => "age DESC",
|
53
|
+
:per_page => 2,
|
54
|
+
:page => 1} )
|
55
|
+
result.should == [@doc1, @doc3]
|
56
|
+
result.first.age.should == 27
|
57
|
+
end
|
58
|
+
|
59
|
+
should "withstand rigor" do
|
60
|
+
result = @document.paginate({
|
61
|
+
:per_page => 1,
|
62
|
+
:page => 1,
|
63
|
+
:order => 'age desc',
|
64
|
+
:last_name => 'Nunemaker'
|
65
|
+
})
|
66
|
+
result.should == [@doc1]
|
67
|
+
result.total_entries.should == 2
|
68
|
+
result.total_pages.should == 2
|
69
|
+
|
70
|
+
result = @document.paginate({
|
71
|
+
:per_page => 1,
|
72
|
+
:page => 2,
|
73
|
+
:order => 'age desc',
|
74
|
+
:last_name => 'Nunemaker'
|
75
|
+
})
|
76
|
+
result.should == [@doc3]
|
77
|
+
result.total_entries.should == 2
|
78
|
+
result.total_pages.should == 2
|
79
|
+
|
80
|
+
result = @document.paginate({
|
81
|
+
:per_page => 2,
|
82
|
+
:page => 1,
|
83
|
+
:order => 'age desc',
|
84
|
+
:last_name => 'Nunemaker'
|
85
|
+
})
|
86
|
+
result.should == [@doc1, @doc3]
|
87
|
+
result.total_entries.should == 2
|
88
|
+
result.total_pages.should == 1
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,175 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class ProtectedTest < Test::Unit::TestCase
|
4
|
+
context 'A document with protected attributes' do
|
5
|
+
setup do
|
6
|
+
@doc_class = Doc do
|
7
|
+
key :name, String
|
8
|
+
key :admin, Boolean, :default => false
|
9
|
+
|
10
|
+
attr_protected :admin
|
11
|
+
end
|
12
|
+
|
13
|
+
@doc = @doc_class.create(:name => 'Steve Sloan')
|
14
|
+
end
|
15
|
+
|
16
|
+
should "have protected attributes class method" do
|
17
|
+
@doc_class.protected_attributes.should == [:admin].to_set
|
18
|
+
end
|
19
|
+
|
20
|
+
should "default protected attributes to nil" do
|
21
|
+
Doc().protected_attributes.should be_nil
|
22
|
+
end
|
23
|
+
|
24
|
+
should "have protected attributes instance method" do
|
25
|
+
@doc.protected_attributes.should equal(@doc_class.protected_attributes)
|
26
|
+
end
|
27
|
+
|
28
|
+
should "raise error if there are accessible attributes" do
|
29
|
+
doc = Doc('Post')
|
30
|
+
doc.attr_accessible :name
|
31
|
+
lambda { doc.attr_protected :admin }.
|
32
|
+
should raise_error(/Declare either attr_protected or attr_accessible for Post/)
|
33
|
+
end
|
34
|
+
|
35
|
+
should "know if using protected attributes" do
|
36
|
+
@doc_class.protected_attributes?.should be(true)
|
37
|
+
Doc().protected_attributes?.should be(false)
|
38
|
+
end
|
39
|
+
|
40
|
+
should "work with :protected shortcut when defining key" do
|
41
|
+
Doc() do
|
42
|
+
key :user_id, ObjectId, :protected => true
|
43
|
+
end.protected_attributes.should == [:user_id].to_set
|
44
|
+
end
|
45
|
+
|
46
|
+
should "assign protected attribute through accessor" do
|
47
|
+
@doc.admin = true
|
48
|
+
@doc.admin.should be_true
|
49
|
+
end
|
50
|
+
|
51
|
+
should "ignore protected attribute on #initialize" do
|
52
|
+
doc = @doc_class.new(:name => 'John', :admin => true)
|
53
|
+
doc.admin.should be_false
|
54
|
+
doc.name.should == 'John'
|
55
|
+
end
|
56
|
+
|
57
|
+
should "not ignore protected attributes on #initialize from the database" do
|
58
|
+
doc = @doc_class.new(:name => 'John')
|
59
|
+
doc.admin = true
|
60
|
+
doc.save!
|
61
|
+
|
62
|
+
doc = @doc_class.first(:name => 'John')
|
63
|
+
doc.admin.should be_true
|
64
|
+
doc.name.should == 'John'
|
65
|
+
end
|
66
|
+
|
67
|
+
should "ignore protected attribute on #update_attributes" do
|
68
|
+
@doc.update_attributes(:name => 'Ren Hoek', :admin => true)
|
69
|
+
@doc.name.should == 'Ren Hoek'
|
70
|
+
@doc.admin.should be_false
|
71
|
+
end
|
72
|
+
|
73
|
+
should "ignore protected attribute on #update_attributes!" do
|
74
|
+
@doc.update_attributes!(:name => 'Stimpson J. Cat', :admin => true)
|
75
|
+
@doc.name.should == 'Stimpson J. Cat'
|
76
|
+
@doc.admin.should be_false
|
77
|
+
end
|
78
|
+
|
79
|
+
should "be indifferent to whether the protected keys are strings or symbols" do
|
80
|
+
@doc.update_attributes!("name" => 'Stimpson J. Cat', "admin" => true)
|
81
|
+
@doc.name.should == 'Stimpson J. Cat'
|
82
|
+
@doc.admin.should be_false
|
83
|
+
end
|
84
|
+
|
85
|
+
should "accept nil as constructor's argument without raising exception" do
|
86
|
+
lambda { @doc_class.new(nil) }.should_not raise_error
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
context "Single collection inherited protected attributes" do
|
91
|
+
setup do
|
92
|
+
class ::GrandParent
|
93
|
+
include MongoMapper::Document
|
94
|
+
|
95
|
+
key :site_id, ObjectId
|
96
|
+
attr_protected :site_id
|
97
|
+
end
|
98
|
+
GrandParent.collection.remove
|
99
|
+
|
100
|
+
class ::Child < ::GrandParent
|
101
|
+
key :position, Integer
|
102
|
+
|
103
|
+
attr_protected :position
|
104
|
+
end
|
105
|
+
|
106
|
+
class ::GrandChild < ::Child; end
|
107
|
+
|
108
|
+
class ::OtherChild < ::GrandParent
|
109
|
+
key :blog_id, ObjectId
|
110
|
+
|
111
|
+
attr_protected :blog_id
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
teardown do
|
116
|
+
Object.send :remove_const, 'GrandParent' if defined?(::GrandParent)
|
117
|
+
Object.send :remove_const, 'Child' if defined?(::Child)
|
118
|
+
Object.send :remove_const, 'GrandChild' if defined?(::GrandChild)
|
119
|
+
Object.send :remove_const, 'OtherChild' if defined?(::OtherChild)
|
120
|
+
end
|
121
|
+
|
122
|
+
should "share keys down the inheritance trail" do
|
123
|
+
GrandParent.protected_attributes.should == [:site_id].to_set
|
124
|
+
Child.protected_attributes.should == [:site_id, :position].to_set
|
125
|
+
GrandChild.protected_attributes.should == [:site_id, :position].to_set
|
126
|
+
OtherChild.protected_attributes.should == [:site_id, :blog_id].to_set
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
context 'An embedded document with protected attributes' do
|
131
|
+
setup do
|
132
|
+
@doc_class = Doc('Project')
|
133
|
+
@edoc_class = EDoc('Person') do
|
134
|
+
key :name, String
|
135
|
+
key :admin, Boolean, :default => false
|
136
|
+
|
137
|
+
attr_protected :admin
|
138
|
+
end
|
139
|
+
@doc_class.many :people, :class => @edoc_class
|
140
|
+
|
141
|
+
@doc = @doc_class.create(:title => 'MongoMapper')
|
142
|
+
@edoc = @edoc_class.new(:name => 'Steve Sloan')
|
143
|
+
@doc.people << @edoc
|
144
|
+
end
|
145
|
+
|
146
|
+
should "have protected attributes class method" do
|
147
|
+
@edoc_class.protected_attributes.should == [:admin].to_set
|
148
|
+
end
|
149
|
+
|
150
|
+
should "default protected attributes to nil" do
|
151
|
+
EDoc().protected_attributes.should be_nil
|
152
|
+
end
|
153
|
+
|
154
|
+
should "have protected attributes instance method" do
|
155
|
+
@edoc.protected_attributes.should equal(@edoc_class.protected_attributes)
|
156
|
+
end
|
157
|
+
|
158
|
+
should "assign protected attribute through accessor" do
|
159
|
+
@edoc.admin = true
|
160
|
+
@edoc.admin.should be_true
|
161
|
+
end
|
162
|
+
|
163
|
+
should "ignore protected attribute on #update_attributes" do
|
164
|
+
@edoc.update_attributes(:name => 'Ren Hoek', :admin => true)
|
165
|
+
@edoc.name.should == 'Ren Hoek'
|
166
|
+
@edoc.admin.should be_false
|
167
|
+
end
|
168
|
+
|
169
|
+
should "ignore protected attribute on #update_attributes!" do
|
170
|
+
@edoc.update_attributes!(:name => 'Stimpson J. Cat', :admin => true)
|
171
|
+
@edoc.name.should == 'Stimpson J. Cat'
|
172
|
+
@edoc.admin.should be_false
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
@@ -0,0 +1,873 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class QueryingTesting < Test::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
@document = Doc do
|
6
|
+
key :first_name, String
|
7
|
+
key :last_name, String
|
8
|
+
key :age, Integer
|
9
|
+
key :date, Date
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
context ".query" do
|
14
|
+
setup do
|
15
|
+
@query = @document.query
|
16
|
+
end
|
17
|
+
|
18
|
+
should "set model to self" do
|
19
|
+
@query.model.should == @document
|
20
|
+
end
|
21
|
+
|
22
|
+
should "always return new instance" do
|
23
|
+
@document.query.should_not equal(@query)
|
24
|
+
end
|
25
|
+
|
26
|
+
should "apply options" do
|
27
|
+
@document.query(:foo => 'bar')[:foo].should == 'bar'
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context ".criteria_hash" do
|
32
|
+
setup do
|
33
|
+
@hash = @document.criteria_hash
|
34
|
+
end
|
35
|
+
|
36
|
+
should "set object id keys on hash" do
|
37
|
+
@hash.object_ids.should == [:_id]
|
38
|
+
end
|
39
|
+
|
40
|
+
should "always return new instance" do
|
41
|
+
@document.criteria_hash.should_not equal(@hash)
|
42
|
+
end
|
43
|
+
|
44
|
+
should "apply provided criteria" do
|
45
|
+
@document.criteria_hash(:foo => 'bar')[:foo].should == 'bar'
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
context ".create (single document)" do
|
50
|
+
setup do
|
51
|
+
@doc = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
|
52
|
+
end
|
53
|
+
|
54
|
+
should "create a document in correct collection" do
|
55
|
+
@document.count.should == 1
|
56
|
+
end
|
57
|
+
|
58
|
+
should "automatically set id" do
|
59
|
+
@doc.id.should be_instance_of(BSON::ObjectID)
|
60
|
+
@doc._id.should be_instance_of(BSON::ObjectID)
|
61
|
+
end
|
62
|
+
|
63
|
+
should "no longer be new?" do
|
64
|
+
@doc.new?.should be_false
|
65
|
+
end
|
66
|
+
|
67
|
+
should "return instance of document" do
|
68
|
+
@doc.should be_instance_of(@document)
|
69
|
+
@doc.first_name.should == 'John'
|
70
|
+
@doc.last_name.should == 'Nunemaker'
|
71
|
+
@doc.age.should == 27
|
72
|
+
end
|
73
|
+
|
74
|
+
should "not fail if no attributes provided" do
|
75
|
+
document = Doc()
|
76
|
+
lambda { document.create }.should change { document.count }.by(1)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
context ".create (multiple documents)" do
|
81
|
+
setup do
|
82
|
+
@docs = @document.create([
|
83
|
+
{:first_name => 'John', :last_name => 'Nunemaker', :age => '27'},
|
84
|
+
{:first_name => 'Steve', :last_name => 'Smith', :age => '28'},
|
85
|
+
])
|
86
|
+
end
|
87
|
+
|
88
|
+
should "create multiple documents" do
|
89
|
+
@document.count.should == 2
|
90
|
+
end
|
91
|
+
|
92
|
+
should "return an array of doc instances" do
|
93
|
+
@docs.map do |doc|
|
94
|
+
doc.should be_instance_of(@document)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
context ".update (single document)" do
|
100
|
+
setup do
|
101
|
+
doc = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
|
102
|
+
@doc = @document.update(doc._id, {:age => 40})
|
103
|
+
end
|
104
|
+
|
105
|
+
should "update attributes provided" do
|
106
|
+
@doc.age.should == 40
|
107
|
+
end
|
108
|
+
|
109
|
+
should "not update existing attributes that were not set to update" do
|
110
|
+
@doc.first_name.should == 'John'
|
111
|
+
@doc.last_name.should == 'Nunemaker'
|
112
|
+
end
|
113
|
+
|
114
|
+
should "not create new document" do
|
115
|
+
@document.count.should == 1
|
116
|
+
end
|
117
|
+
|
118
|
+
should "raise error if not provided id" do
|
119
|
+
doc = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
|
120
|
+
lambda { @document.update }.should raise_error(ArgumentError)
|
121
|
+
end
|
122
|
+
|
123
|
+
should "raise error if not provided attributes" do
|
124
|
+
doc = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
|
125
|
+
lambda { @document.update(doc._id) }.should raise_error(ArgumentError)
|
126
|
+
lambda { @document.update(doc._id, [1]) }.should raise_error(ArgumentError)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
context ".update (multiple documents)" do
|
131
|
+
setup do
|
132
|
+
@doc1 = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
|
133
|
+
@doc2 = @document.create({:first_name => 'Steve', :last_name => 'Smith', :age => '28'})
|
134
|
+
|
135
|
+
@docs = @document.update({
|
136
|
+
@doc1._id => {:age => 30},
|
137
|
+
@doc2._id => {:age => 30},
|
138
|
+
})
|
139
|
+
end
|
140
|
+
|
141
|
+
should "not create any new documents" do
|
142
|
+
@document.count.should == 2
|
143
|
+
end
|
144
|
+
|
145
|
+
should "should return an array of doc instances" do
|
146
|
+
@docs.map do |doc|
|
147
|
+
doc.should be_instance_of(@document)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
should "update the documents" do
|
152
|
+
@document.find(@doc1._id).age.should == 30
|
153
|
+
@document.find(@doc2._id).age.should == 30
|
154
|
+
end
|
155
|
+
|
156
|
+
should "raise error if not a hash" do
|
157
|
+
lambda { @document.update([1, 2]) }.should raise_error(ArgumentError)
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
context ".find" do
|
162
|
+
setup do
|
163
|
+
@doc1 = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
|
164
|
+
@doc2 = @document.create({:first_name => 'Steve', :last_name => 'Smith', :age => '28'})
|
165
|
+
@doc3 = @document.create({:first_name => 'Steph', :last_name => 'Nunemaker', :age => '26'})
|
166
|
+
end
|
167
|
+
|
168
|
+
should "return nil if nothing provided for find" do
|
169
|
+
@document.find.should be_nil
|
170
|
+
end
|
171
|
+
|
172
|
+
should "raise document not found if nothing provided for find!" do
|
173
|
+
assert_raises(MongoMapper::DocumentNotFound) do
|
174
|
+
@document.find!
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
context "(with a single id)" do
|
179
|
+
should "work" do
|
180
|
+
@document.find(@doc1._id).should == @doc1
|
181
|
+
end
|
182
|
+
|
183
|
+
should "return nil if document not found with find" do
|
184
|
+
@document.find(123).should be_nil
|
185
|
+
end
|
186
|
+
|
187
|
+
should "raise error if document not found with find!" do
|
188
|
+
assert_raises(MongoMapper::DocumentNotFound) { @document.find!(123) }
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
context "(with multiple id's)" do
|
193
|
+
should "work as arguments" do
|
194
|
+
@document.find(@doc1._id, @doc2._id).should == [@doc1, @doc2]
|
195
|
+
end
|
196
|
+
|
197
|
+
should "work as arguments with string ids" do
|
198
|
+
@document.find(@doc1._id.to_s, @doc2._id.to_s).should == [@doc1, @doc2]
|
199
|
+
end
|
200
|
+
|
201
|
+
should "work as array" do
|
202
|
+
@document.find([@doc1._id, @doc2._id]).should == [@doc1, @doc2]
|
203
|
+
end
|
204
|
+
|
205
|
+
should "work as array with string ids" do
|
206
|
+
@document.find([@doc1._id.to_s, @doc2._id.to_s]).should == [@doc1, @doc2]
|
207
|
+
end
|
208
|
+
|
209
|
+
should "compact not found when using find" do
|
210
|
+
@document.find(@doc1._id, BSON::ObjectID.new.to_s).should == [@doc1]
|
211
|
+
end
|
212
|
+
|
213
|
+
should "raise error if not all found when using find!" do
|
214
|
+
assert_raises(MongoMapper::DocumentNotFound) do
|
215
|
+
@document.find!(@doc1._id, BSON::ObjectID.new.to_s)
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
should "return array if array with one element" do
|
220
|
+
@document.find([@doc1._id]).should == [@doc1]
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
should "be able to find using condition auto-detection" do
|
225
|
+
@document.first(:first_name => 'John').should == @doc1
|
226
|
+
@document.all(:last_name => 'Nunemaker', :order => 'age desc').should == [@doc1, @doc3]
|
227
|
+
end
|
228
|
+
|
229
|
+
context "#all" do
|
230
|
+
should "find all documents with options" do
|
231
|
+
@document.all(:order => 'first_name').should == [@doc1, @doc3, @doc2]
|
232
|
+
@document.all(:last_name => 'Nunemaker', :order => 'age desc').should == [@doc1, @doc3]
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
context "#first" do
|
237
|
+
should "find first document with options" do
|
238
|
+
@document.first(:order => 'first_name').should == @doc1
|
239
|
+
@document.first(:age => 28).should == @doc2
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
context "#last" do
|
244
|
+
should "find last document with options" do
|
245
|
+
@document.last(:order => 'age').should == @doc2
|
246
|
+
@document.last(:order => 'age', :age => 28).should == @doc2
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
context "#find_each" do
|
251
|
+
should "yield all documents found based on options" do
|
252
|
+
yield_documents = []
|
253
|
+
@document.find_each(:order => "first_name") {|doc| yield_documents << doc }
|
254
|
+
yield_documents.should == [@doc1, @doc3, @doc2]
|
255
|
+
|
256
|
+
yield_documents = []
|
257
|
+
@document.find_each(:last_name => 'Nunemaker', :order => 'age desc') {|doc| yield_documents << doc }
|
258
|
+
yield_documents.should == [@doc1, @doc3]
|
259
|
+
end
|
260
|
+
end
|
261
|
+
end # finding documents
|
262
|
+
|
263
|
+
context ".find_by_id" do
|
264
|
+
setup do
|
265
|
+
@doc1 = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
|
266
|
+
@doc2 = @document.create({:first_name => 'Steve', :last_name => 'Smith', :age => '28'})
|
267
|
+
end
|
268
|
+
|
269
|
+
should "be able to find by id" do
|
270
|
+
@document.find_by_id(@doc1._id).should == @doc1
|
271
|
+
@document.find_by_id(@doc2._id).should == @doc2
|
272
|
+
end
|
273
|
+
|
274
|
+
should "return nil if document not found" do
|
275
|
+
@document.find_by_id(1234).should be_nil
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
279
|
+
context ".first_or_create" do
|
280
|
+
should "find if exists" do
|
281
|
+
created = @document.create(:first_name => 'John', :last_name => 'Nunemaker')
|
282
|
+
lambda {
|
283
|
+
found = @document.first_or_create(:first_name => 'John', :last_name => 'Nunemaker')
|
284
|
+
found.should == created
|
285
|
+
}.should_not change { @document.count }
|
286
|
+
end
|
287
|
+
|
288
|
+
should "create if not found" do
|
289
|
+
lambda {
|
290
|
+
created = @document.first_or_create(:first_name => 'John', :last_name => 'Nunemaker')
|
291
|
+
created.first_name.should == 'John'
|
292
|
+
created.last_name.should == 'Nunemaker'
|
293
|
+
}.should change { @document.count }.by(1)
|
294
|
+
end
|
295
|
+
|
296
|
+
should "disregard non-keys when creating, but use them in the query" do
|
297
|
+
assert_nothing_raised do
|
298
|
+
@document.create(:first_name => 'John', :age => 9)
|
299
|
+
lambda {
|
300
|
+
@document.first_or_create(:first_name => 'John', :age.gt => 10).first_name.should == 'John'
|
301
|
+
}.should change { @document.count }.by(1)
|
302
|
+
end
|
303
|
+
end
|
304
|
+
end
|
305
|
+
|
306
|
+
context ".first_or_new" do
|
307
|
+
should "find if exists" do
|
308
|
+
created = @document.create(:first_name => 'John', :last_name => 'Nunemaker')
|
309
|
+
lambda {
|
310
|
+
found = @document.first_or_new(:first_name => 'John', :last_name => 'Nunemaker')
|
311
|
+
found.should == created
|
312
|
+
}.should_not change { @document.count }
|
313
|
+
end
|
314
|
+
|
315
|
+
should "initialize if not found" do
|
316
|
+
lambda {
|
317
|
+
created = @document.first_or_new(:first_name => 'John', :last_name => 'Nunemaker')
|
318
|
+
created.first_name.should == 'John'
|
319
|
+
created.last_name.should == 'Nunemaker'
|
320
|
+
created.should be_new
|
321
|
+
}.should_not change { @document.count }
|
322
|
+
end
|
323
|
+
|
324
|
+
should "disregard non-keys when initializing, but use them in the query" do
|
325
|
+
assert_nothing_raised do
|
326
|
+
@document.create(:first_name => 'John', :age => 9)
|
327
|
+
@document.first_or_new(:first_name => 'John', :age.gt => 10).first_name.should == 'John'
|
328
|
+
end
|
329
|
+
end
|
330
|
+
end
|
331
|
+
|
332
|
+
context ".delete (single document)" do
|
333
|
+
setup do
|
334
|
+
@doc1 = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
|
335
|
+
@doc2 = @document.create({:first_name => 'Steve', :last_name => 'Smith', :age => '28'})
|
336
|
+
@document.delete(@doc1._id)
|
337
|
+
end
|
338
|
+
|
339
|
+
should "remove document from collection" do
|
340
|
+
@document.count.should == 1
|
341
|
+
end
|
342
|
+
|
343
|
+
should "not remove other documents" do
|
344
|
+
@document.find(@doc2._id).should_not be(nil)
|
345
|
+
end
|
346
|
+
end
|
347
|
+
|
348
|
+
context ".delete (multiple documents)" do
|
349
|
+
should "work with multiple arguments" do
|
350
|
+
@doc1 = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
|
351
|
+
@doc2 = @document.create({:first_name => 'Steve', :last_name => 'Smith', :age => '28'})
|
352
|
+
@doc3 = @document.create({:first_name => 'Steph', :last_name => 'Nunemaker', :age => '26'})
|
353
|
+
@document.delete(@doc1._id, @doc2._id)
|
354
|
+
|
355
|
+
@document.count.should == 1
|
356
|
+
end
|
357
|
+
|
358
|
+
should "work with array as argument" do
|
359
|
+
@doc1 = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
|
360
|
+
@doc2 = @document.create({:first_name => 'Steve', :last_name => 'Smith', :age => '28'})
|
361
|
+
@doc3 = @document.create({:first_name => 'Steph', :last_name => 'Nunemaker', :age => '26'})
|
362
|
+
@document.delete([@doc1._id, @doc2._id])
|
363
|
+
|
364
|
+
@document.count.should == 1
|
365
|
+
end
|
366
|
+
end
|
367
|
+
|
368
|
+
context ".delete_all" do
|
369
|
+
setup do
|
370
|
+
@doc1 = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
|
371
|
+
@doc2 = @document.create({:first_name => 'Steve', :last_name => 'Smith', :age => '28'})
|
372
|
+
@doc3 = @document.create({:first_name => 'Steph', :last_name => 'Nunemaker', :age => '26'})
|
373
|
+
end
|
374
|
+
|
375
|
+
should "remove all documents when given no conditions" do
|
376
|
+
@document.delete_all
|
377
|
+
@document.count.should == 0
|
378
|
+
end
|
379
|
+
|
380
|
+
should "only remove matching documents when given conditions" do
|
381
|
+
@document.delete_all({:first_name => 'John'})
|
382
|
+
@document.count.should == 2
|
383
|
+
end
|
384
|
+
|
385
|
+
should "convert the conditions to mongo criteria" do
|
386
|
+
@document.delete_all(:age => [26, 27])
|
387
|
+
@document.count.should == 1
|
388
|
+
end
|
389
|
+
end
|
390
|
+
|
391
|
+
context ".destroy (single document)" do
|
392
|
+
setup do
|
393
|
+
@doc1 = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
|
394
|
+
@doc2 = @document.create({:first_name => 'Steve', :last_name => 'Smith', :age => '28'})
|
395
|
+
@document.destroy(@doc1._id)
|
396
|
+
end
|
397
|
+
|
398
|
+
should "remove document from collection" do
|
399
|
+
@document.count.should == 1
|
400
|
+
end
|
401
|
+
|
402
|
+
should "not remove other documents" do
|
403
|
+
@document.find(@doc2._id).should_not be(nil)
|
404
|
+
end
|
405
|
+
end
|
406
|
+
|
407
|
+
context ".destroy (multiple documents)" do
|
408
|
+
should "work with multiple arguments" do
|
409
|
+
@doc1 = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
|
410
|
+
@doc2 = @document.create({:first_name => 'Steve', :last_name => 'Smith', :age => '28'})
|
411
|
+
@doc3 = @document.create({:first_name => 'Steph', :last_name => 'Nunemaker', :age => '26'})
|
412
|
+
@document.destroy(@doc1._id, @doc2._id)
|
413
|
+
|
414
|
+
@document.count.should == 1
|
415
|
+
end
|
416
|
+
|
417
|
+
should "work with array as argument" do
|
418
|
+
@doc1 = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
|
419
|
+
@doc2 = @document.create({:first_name => 'Steve', :last_name => 'Smith', :age => '28'})
|
420
|
+
@doc3 = @document.create({:first_name => 'Steph', :last_name => 'Nunemaker', :age => '26'})
|
421
|
+
@document.destroy([@doc1._id, @doc2._id])
|
422
|
+
|
423
|
+
@document.count.should == 1
|
424
|
+
end
|
425
|
+
end
|
426
|
+
|
427
|
+
context ".destroy_all" do
|
428
|
+
setup do
|
429
|
+
@doc1 = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
|
430
|
+
@doc2 = @document.create({:first_name => 'Steve', :last_name => 'Smith', :age => '28'})
|
431
|
+
@doc3 = @document.create({:first_name => 'Steph', :last_name => 'Nunemaker', :age => '26'})
|
432
|
+
end
|
433
|
+
|
434
|
+
should "remove all documents when given no conditions" do
|
435
|
+
@document.destroy_all
|
436
|
+
@document.count.should == 0
|
437
|
+
end
|
438
|
+
|
439
|
+
should "only remove matching documents when given conditions" do
|
440
|
+
@document.destroy_all(:first_name => 'John')
|
441
|
+
@document.count.should == 2
|
442
|
+
@document.destroy_all(:age => 26)
|
443
|
+
@document.count.should == 1
|
444
|
+
end
|
445
|
+
|
446
|
+
should "convert the conditions to mongo criteria" do
|
447
|
+
@document.destroy_all(:age => [26, 27])
|
448
|
+
@document.count.should == 1
|
449
|
+
end
|
450
|
+
end
|
451
|
+
|
452
|
+
context ".count" do
|
453
|
+
setup do
|
454
|
+
@doc1 = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
|
455
|
+
@doc2 = @document.create({:first_name => 'Steve', :last_name => 'Smith', :age => '28'})
|
456
|
+
@doc3 = @document.create({:first_name => 'Steph', :last_name => 'Nunemaker', :age => '26'})
|
457
|
+
end
|
458
|
+
|
459
|
+
should "count all with no arguments" do
|
460
|
+
@document.count.should == 3
|
461
|
+
end
|
462
|
+
|
463
|
+
should "return 0 if there are no documents in the collection" do
|
464
|
+
@document.delete_all
|
465
|
+
@document.count.should == 0
|
466
|
+
end
|
467
|
+
|
468
|
+
should "return 0 if the collection does not exist" do
|
469
|
+
klass = Doc do
|
470
|
+
set_collection_name 'foobarbazwickdoesnotexist'
|
471
|
+
end
|
472
|
+
|
473
|
+
klass.count.should == 0
|
474
|
+
end
|
475
|
+
|
476
|
+
should "return count for matching documents if conditions provided" do
|
477
|
+
@document.count(:age => 27).should == 1
|
478
|
+
end
|
479
|
+
|
480
|
+
should "convert the conditions to mongo criteria" do
|
481
|
+
@document.count(:age => [26, 27]).should == 2
|
482
|
+
end
|
483
|
+
end
|
484
|
+
|
485
|
+
context ".exists?" do
|
486
|
+
setup do
|
487
|
+
@doc = @document.create(:first_name => "James", :age => 27)
|
488
|
+
end
|
489
|
+
|
490
|
+
should "be true when at least one document exists" do
|
491
|
+
@document.exists?.should == true
|
492
|
+
end
|
493
|
+
|
494
|
+
should "be false when no documents exist" do
|
495
|
+
@doc.destroy
|
496
|
+
@document.exists?.should == false
|
497
|
+
end
|
498
|
+
|
499
|
+
should "be true when at least one document exists that matches the conditions" do
|
500
|
+
@document.exists?(:first_name => "James").should == true
|
501
|
+
end
|
502
|
+
|
503
|
+
should "be false when no documents exist with the provided conditions" do
|
504
|
+
@document.exists?(:first_name => "Jean").should == false
|
505
|
+
end
|
506
|
+
end
|
507
|
+
|
508
|
+
context ".where" do
|
509
|
+
setup do
|
510
|
+
@doc1 = @document.create(:first_name => 'John', :last_name => 'Nunemaker', :age => '27')
|
511
|
+
@doc2 = @document.create(:first_name => 'Steve', :last_name => 'Smith', :age => '28')
|
512
|
+
@doc3 = @document.create(:first_name => 'Steph', :last_name => 'Nunemaker', :age => '26')
|
513
|
+
@query = @document.where(:last_name => 'Nunemaker')
|
514
|
+
end
|
515
|
+
|
516
|
+
should "fetch documents when kicker called" do
|
517
|
+
docs = @query.all
|
518
|
+
docs.should include(@doc1)
|
519
|
+
docs.should include(@doc3)
|
520
|
+
docs.should_not include(@doc2)
|
521
|
+
end
|
522
|
+
|
523
|
+
should "be chainable" do
|
524
|
+
@query.sort(:age).first.should == @doc3
|
525
|
+
end
|
526
|
+
end
|
527
|
+
|
528
|
+
context ".fields" do
|
529
|
+
setup do
|
530
|
+
@doc1 = @document.create(:first_name => 'John', :last_name => 'Nunemaker', :age => '27')
|
531
|
+
@doc2 = @document.create(:first_name => 'Steve', :last_name => 'Smith', :age => '28')
|
532
|
+
@doc3 = @document.create(:first_name => 'Steph', :last_name => 'Nunemaker', :age => '26')
|
533
|
+
@query = @document.fields(:age)
|
534
|
+
end
|
535
|
+
|
536
|
+
should "fetch documents when kicker called" do
|
537
|
+
docs = @query.all
|
538
|
+
docs.should include(@doc1)
|
539
|
+
docs.should include(@doc3)
|
540
|
+
docs.should include(@doc2)
|
541
|
+
docs.each do |doc|
|
542
|
+
doc.age.should_not be_nil
|
543
|
+
doc.first_name.should be_nil # key was not loaded
|
544
|
+
doc.last_name.should be_nil # key was not loaded
|
545
|
+
end
|
546
|
+
end
|
547
|
+
|
548
|
+
should "be chainable" do
|
549
|
+
@query.sort(:age).all.map(&:age).should == [26, 27, 28]
|
550
|
+
end
|
551
|
+
end
|
552
|
+
|
553
|
+
context ".limit" do
|
554
|
+
setup do
|
555
|
+
@doc1 = @document.create(:first_name => 'John', :last_name => 'Nunemaker', :age => '27')
|
556
|
+
@doc2 = @document.create(:first_name => 'Steve', :last_name => 'Smith', :age => '28')
|
557
|
+
@doc3 = @document.create(:first_name => 'Steph', :last_name => 'Nunemaker', :age => '26')
|
558
|
+
@query = @document.limit(2)
|
559
|
+
end
|
560
|
+
|
561
|
+
should "fetch documents when kicker called" do
|
562
|
+
docs = @query.all
|
563
|
+
docs.size.should == 2
|
564
|
+
end
|
565
|
+
|
566
|
+
should "be chainable" do
|
567
|
+
result = [26, 27]
|
568
|
+
@query.sort(:age).all.map(&:age).should == result
|
569
|
+
@query.count.should > result.size
|
570
|
+
end
|
571
|
+
end
|
572
|
+
|
573
|
+
context ".skip" do
|
574
|
+
setup do
|
575
|
+
@doc1 = @document.create(:first_name => 'John', :last_name => 'Nunemaker', :age => '27')
|
576
|
+
@doc2 = @document.create(:first_name => 'Steve', :last_name => 'Smith', :age => '28')
|
577
|
+
@doc3 = @document.create(:first_name => 'Steph', :last_name => 'Nunemaker', :age => '26')
|
578
|
+
@query = @document.skip(1)
|
579
|
+
end
|
580
|
+
|
581
|
+
should "fetch documents when kicker called" do
|
582
|
+
docs = @query.all
|
583
|
+
docs.size.should == 2 # skipping 1 out of 3
|
584
|
+
end
|
585
|
+
|
586
|
+
should "be chainable" do
|
587
|
+
result = [27, 28]
|
588
|
+
@query.sort(:age).all.map(&:age).should == result
|
589
|
+
@query.count.should > result.size
|
590
|
+
end
|
591
|
+
end
|
592
|
+
|
593
|
+
context ".sort" do
|
594
|
+
setup do
|
595
|
+
@doc1 = @document.create(:first_name => 'John', :last_name => 'Nunemaker', :age => '27')
|
596
|
+
@doc2 = @document.create(:first_name => 'Steve', :last_name => 'Smith', :age => '28')
|
597
|
+
@doc3 = @document.create(:first_name => 'Steph', :last_name => 'Nunemaker', :age => '26')
|
598
|
+
@query = @document.sort(:age)
|
599
|
+
end
|
600
|
+
|
601
|
+
should "fetch documents when kicker called" do
|
602
|
+
@query.all.should == [@doc3, @doc1, @doc2]
|
603
|
+
end
|
604
|
+
|
605
|
+
should "be chainable" do
|
606
|
+
result = [28]
|
607
|
+
@query.skip(2).all.map(&:age).should == result
|
608
|
+
@query.count.should > result.size
|
609
|
+
end
|
610
|
+
end
|
611
|
+
|
612
|
+
context "#update_attributes (new document)" do
|
613
|
+
setup do
|
614
|
+
@doc = @document.new(:first_name => 'John', :age => '27')
|
615
|
+
@doc.update_attributes(:first_name => 'Johnny', :age => 30)
|
616
|
+
end
|
617
|
+
|
618
|
+
should "insert document into the collection" do
|
619
|
+
@document.count.should == 1
|
620
|
+
end
|
621
|
+
|
622
|
+
should "assign an id for the document" do
|
623
|
+
@doc.id.should be_instance_of(BSON::ObjectID)
|
624
|
+
end
|
625
|
+
|
626
|
+
should "save attributes" do
|
627
|
+
@doc.first_name.should == 'Johnny'
|
628
|
+
@doc.age.should == 30
|
629
|
+
end
|
630
|
+
|
631
|
+
should "update attributes in the database" do
|
632
|
+
doc = @doc.reload
|
633
|
+
doc.should == @doc
|
634
|
+
doc.first_name.should == 'Johnny'
|
635
|
+
doc.age.should == 30
|
636
|
+
end
|
637
|
+
|
638
|
+
should "allow updating custom attributes" do
|
639
|
+
@doc.update_attributes(:gender => 'mALe')
|
640
|
+
@doc.reload.gender.should == 'mALe'
|
641
|
+
end
|
642
|
+
end
|
643
|
+
|
644
|
+
context "#update_attributes (existing document)" do
|
645
|
+
setup do
|
646
|
+
@doc = @document.create(:first_name => 'John', :age => '27')
|
647
|
+
@doc.update_attributes(:first_name => 'Johnny', :age => 30)
|
648
|
+
end
|
649
|
+
|
650
|
+
should "not insert document into collection" do
|
651
|
+
@document.count.should == 1
|
652
|
+
end
|
653
|
+
|
654
|
+
should "update attributes" do
|
655
|
+
@doc.first_name.should == 'Johnny'
|
656
|
+
@doc.age.should == 30
|
657
|
+
end
|
658
|
+
|
659
|
+
should "update attributes in the database" do
|
660
|
+
doc = @doc.reload
|
661
|
+
doc.first_name.should == 'Johnny'
|
662
|
+
doc.age.should == 30
|
663
|
+
end
|
664
|
+
end
|
665
|
+
|
666
|
+
context "#update_attributes (return value)" do
|
667
|
+
setup do
|
668
|
+
@document.key :foo, String, :required => true
|
669
|
+
end
|
670
|
+
|
671
|
+
should "be true if document valid" do
|
672
|
+
@document.new.update_attributes(:foo => 'bar').should be_true
|
673
|
+
end
|
674
|
+
|
675
|
+
should "be false if document not valid" do
|
676
|
+
@document.new.update_attributes({}).should be_false
|
677
|
+
end
|
678
|
+
end
|
679
|
+
|
680
|
+
context "#save (new document)" do
|
681
|
+
setup do
|
682
|
+
@doc = @document.new(:first_name => 'John', :age => '27')
|
683
|
+
@doc.save
|
684
|
+
end
|
685
|
+
|
686
|
+
should "insert document into the collection" do
|
687
|
+
@document.count.should == 1
|
688
|
+
end
|
689
|
+
|
690
|
+
should "assign an id for the document" do
|
691
|
+
@doc.id.should be_instance_of(BSON::ObjectID)
|
692
|
+
end
|
693
|
+
|
694
|
+
should "save attributes" do
|
695
|
+
@doc.first_name.should == 'John'
|
696
|
+
@doc.age.should == 27
|
697
|
+
end
|
698
|
+
|
699
|
+
should "update attributes in the database" do
|
700
|
+
doc = @doc.reload
|
701
|
+
doc.should == @doc
|
702
|
+
doc.first_name.should == 'John'
|
703
|
+
doc.age.should == 27
|
704
|
+
end
|
705
|
+
|
706
|
+
should "allow to add custom attributes to the document" do
|
707
|
+
@doc = @document.new(:first_name => 'David', :age => '26', :gender => 'male', :tags => [1, "2"])
|
708
|
+
@doc.save
|
709
|
+
doc = @doc.reload
|
710
|
+
doc.gender.should == 'male'
|
711
|
+
doc.tags.should == [1, "2"]
|
712
|
+
end
|
713
|
+
|
714
|
+
should "allow to use custom methods to assign properties" do
|
715
|
+
klass = Doc do
|
716
|
+
key :name, String
|
717
|
+
|
718
|
+
def realname=(value)
|
719
|
+
self.name = value
|
720
|
+
end
|
721
|
+
end
|
722
|
+
|
723
|
+
person = klass.new(:realname => 'David')
|
724
|
+
person.save
|
725
|
+
person.reload.name.should == 'David'
|
726
|
+
end
|
727
|
+
|
728
|
+
context "with key of type date" do
|
729
|
+
should "save the date value as a Time object" do
|
730
|
+
doc = @document.new(:first_name => 'John', :age => '27', :date => "2009-12-01")
|
731
|
+
doc.save
|
732
|
+
doc.date.should == Date.new(2009, 12, 1)
|
733
|
+
end
|
734
|
+
end
|
735
|
+
end
|
736
|
+
|
737
|
+
context "#save (existing document)" do
|
738
|
+
setup do
|
739
|
+
@doc = @document.create(:first_name => 'John', :age => '27')
|
740
|
+
@doc.first_name = 'Johnny'
|
741
|
+
@doc.age = 30
|
742
|
+
@doc.save
|
743
|
+
end
|
744
|
+
|
745
|
+
should "not insert document into collection" do
|
746
|
+
@document.count.should == 1
|
747
|
+
end
|
748
|
+
|
749
|
+
should "update attributes" do
|
750
|
+
@doc.first_name.should == 'Johnny'
|
751
|
+
@doc.age.should == 30
|
752
|
+
end
|
753
|
+
|
754
|
+
should "update attributes in the database" do
|
755
|
+
doc = @doc.reload
|
756
|
+
doc.first_name.should == 'Johnny'
|
757
|
+
doc.age.should == 30
|
758
|
+
end
|
759
|
+
|
760
|
+
should "allow updating custom attributes" do
|
761
|
+
@doc = @document.new(:first_name => 'David', :age => '26', :gender => 'male')
|
762
|
+
@doc.gender = 'Male'
|
763
|
+
@doc.save
|
764
|
+
@doc.reload.gender.should == 'Male'
|
765
|
+
end
|
766
|
+
end
|
767
|
+
|
768
|
+
context "#save (with validations off)" do
|
769
|
+
setup do
|
770
|
+
@document = Doc do
|
771
|
+
key :name, String, :required => true
|
772
|
+
end
|
773
|
+
end
|
774
|
+
|
775
|
+
should "insert invalid document" do
|
776
|
+
doc = @document.new
|
777
|
+
doc.expects(:valid?).never
|
778
|
+
doc.save(:validate => false)
|
779
|
+
@document.count.should == 1
|
780
|
+
end
|
781
|
+
end
|
782
|
+
|
783
|
+
context "#save (with options)" do
|
784
|
+
setup do
|
785
|
+
@document = Doc do
|
786
|
+
key :name, String
|
787
|
+
end
|
788
|
+
@document.ensure_index :name, :unique => true
|
789
|
+
end
|
790
|
+
teardown { drop_indexes(@document) }
|
791
|
+
|
792
|
+
should "allow passing safe" do
|
793
|
+
@document.create(:name => 'John')
|
794
|
+
assert_raises(Mongo::OperationFailure) do
|
795
|
+
@document.new(:name => 'John').save(:safe => true)
|
796
|
+
end
|
797
|
+
end
|
798
|
+
|
799
|
+
should "raise argument error if options has unsupported key" do
|
800
|
+
assert_raises(ArgumentError) do
|
801
|
+
@document.new.save(:foo => true)
|
802
|
+
end
|
803
|
+
end
|
804
|
+
end
|
805
|
+
|
806
|
+
context "#save! (with options)" do
|
807
|
+
setup do
|
808
|
+
@document = Doc { key :name, String }
|
809
|
+
@document.ensure_index :name, :unique => true
|
810
|
+
end
|
811
|
+
teardown { drop_indexes(@document) }
|
812
|
+
|
813
|
+
should "allow passing safe" do
|
814
|
+
@document.create(:name => 'John')
|
815
|
+
assert_raises(Mongo::OperationFailure) do
|
816
|
+
@document.new(:name => 'John').save!(:safe => true)
|
817
|
+
end
|
818
|
+
end
|
819
|
+
|
820
|
+
should "raise argument error if options has unsupported key" do
|
821
|
+
assert_raises(ArgumentError) do
|
822
|
+
@document.new.save!(:foo => true)
|
823
|
+
end
|
824
|
+
end
|
825
|
+
|
826
|
+
should "raise argument error if using validate as that would be pointless with save!" do
|
827
|
+
assert_raises(ArgumentError) do
|
828
|
+
@document.new.save!(:validate => false)
|
829
|
+
end
|
830
|
+
end
|
831
|
+
end
|
832
|
+
|
833
|
+
context "#destroy" do
|
834
|
+
setup do
|
835
|
+
@doc = @document.create(:first_name => 'John', :age => '27')
|
836
|
+
@doc.destroy
|
837
|
+
end
|
838
|
+
|
839
|
+
should "remove the document from the collection" do
|
840
|
+
@document.count.should == 0
|
841
|
+
end
|
842
|
+
end
|
843
|
+
|
844
|
+
context "#delete" do
|
845
|
+
setup do
|
846
|
+
@doc1 = @document.create(:first_name => 'John', :last_name => 'Nunemaker', :age => '27')
|
847
|
+
@doc2 = @document.create(:first_name => 'Steve', :last_name => 'Smith', :age => '28')
|
848
|
+
|
849
|
+
@document.class_eval do
|
850
|
+
before_destroy :before_destroy_callback
|
851
|
+
after_destroy :after_destroy_callback
|
852
|
+
|
853
|
+
def history; @history ||= [] end
|
854
|
+
def before_destroy_callback; history << :after_destroy end
|
855
|
+
def after_destroy_callback; history << :after_destroy end
|
856
|
+
end
|
857
|
+
|
858
|
+
@doc1.delete
|
859
|
+
end
|
860
|
+
|
861
|
+
should "remove document from collection" do
|
862
|
+
@document.count.should == 1
|
863
|
+
end
|
864
|
+
|
865
|
+
should "not remove other documents" do
|
866
|
+
@document.find(@doc2.id).should_not be(nil)
|
867
|
+
end
|
868
|
+
|
869
|
+
should "not call before/after destroy callbacks" do
|
870
|
+
@doc1.history.should == []
|
871
|
+
end
|
872
|
+
end
|
873
|
+
end
|