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