mongomodel 0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +22 -0
- data/README.md +34 -0
- data/Rakefile +47 -0
- data/bin/console +45 -0
- data/lib/mongomodel.rb +92 -0
- data/lib/mongomodel/attributes/mongo.rb +40 -0
- data/lib/mongomodel/attributes/store.rb +30 -0
- data/lib/mongomodel/attributes/typecasting.rb +51 -0
- data/lib/mongomodel/concerns/abstract_class.rb +17 -0
- data/lib/mongomodel/concerns/activemodel.rb +11 -0
- data/lib/mongomodel/concerns/associations.rb +103 -0
- data/lib/mongomodel/concerns/associations/base/association.rb +33 -0
- data/lib/mongomodel/concerns/associations/base/definition.rb +56 -0
- data/lib/mongomodel/concerns/associations/base/proxy.rb +58 -0
- data/lib/mongomodel/concerns/associations/belongs_to.rb +68 -0
- data/lib/mongomodel/concerns/associations/has_many_by_foreign_key.rb +159 -0
- data/lib/mongomodel/concerns/associations/has_many_by_ids.rb +175 -0
- data/lib/mongomodel/concerns/attribute_methods.rb +55 -0
- data/lib/mongomodel/concerns/attribute_methods/before_type_cast.rb +29 -0
- data/lib/mongomodel/concerns/attribute_methods/dirty.rb +35 -0
- data/lib/mongomodel/concerns/attribute_methods/protected.rb +127 -0
- data/lib/mongomodel/concerns/attribute_methods/query.rb +22 -0
- data/lib/mongomodel/concerns/attribute_methods/read.rb +29 -0
- data/lib/mongomodel/concerns/attribute_methods/write.rb +29 -0
- data/lib/mongomodel/concerns/attributes.rb +85 -0
- data/lib/mongomodel/concerns/callbacks.rb +294 -0
- data/lib/mongomodel/concerns/logging.rb +15 -0
- data/lib/mongomodel/concerns/pretty_inspect.rb +29 -0
- data/lib/mongomodel/concerns/properties.rb +69 -0
- data/lib/mongomodel/concerns/record_status.rb +42 -0
- data/lib/mongomodel/concerns/timestamps.rb +32 -0
- data/lib/mongomodel/concerns/validations.rb +38 -0
- data/lib/mongomodel/concerns/validations/associated.rb +46 -0
- data/lib/mongomodel/document.rb +20 -0
- data/lib/mongomodel/document/callbacks.rb +46 -0
- data/lib/mongomodel/document/dynamic_finders.rb +88 -0
- data/lib/mongomodel/document/finders.rb +82 -0
- data/lib/mongomodel/document/indexes.rb +91 -0
- data/lib/mongomodel/document/optimistic_locking.rb +48 -0
- data/lib/mongomodel/document/persistence.rb +143 -0
- data/lib/mongomodel/document/scopes.rb +161 -0
- data/lib/mongomodel/document/validations.rb +68 -0
- data/lib/mongomodel/document/validations/uniqueness.rb +78 -0
- data/lib/mongomodel/embedded_document.rb +42 -0
- data/lib/mongomodel/locale/en.yml +55 -0
- data/lib/mongomodel/support/collection.rb +109 -0
- data/lib/mongomodel/support/configuration.rb +35 -0
- data/lib/mongomodel/support/core_extensions.rb +10 -0
- data/lib/mongomodel/support/exceptions.rb +25 -0
- data/lib/mongomodel/support/mongo_options.rb +177 -0
- data/lib/mongomodel/support/types.rb +35 -0
- data/lib/mongomodel/support/types/array.rb +11 -0
- data/lib/mongomodel/support/types/boolean.rb +25 -0
- data/lib/mongomodel/support/types/custom.rb +38 -0
- data/lib/mongomodel/support/types/date.rb +20 -0
- data/lib/mongomodel/support/types/float.rb +13 -0
- data/lib/mongomodel/support/types/hash.rb +18 -0
- data/lib/mongomodel/support/types/integer.rb +13 -0
- data/lib/mongomodel/support/types/object.rb +21 -0
- data/lib/mongomodel/support/types/string.rb +9 -0
- data/lib/mongomodel/support/types/symbol.rb +9 -0
- data/lib/mongomodel/support/types/time.rb +12 -0
- data/lib/mongomodel/version.rb +3 -0
- data/spec/mongomodel/attributes/store_spec.rb +273 -0
- data/spec/mongomodel/concerns/activemodel_spec.rb +61 -0
- data/spec/mongomodel/concerns/associations/belongs_to_spec.rb +153 -0
- data/spec/mongomodel/concerns/associations/has_many_by_foreign_key_spec.rb +165 -0
- data/spec/mongomodel/concerns/associations/has_many_by_ids_spec.rb +192 -0
- data/spec/mongomodel/concerns/attribute_methods/before_type_cast_spec.rb +46 -0
- data/spec/mongomodel/concerns/attribute_methods/dirty_spec.rb +131 -0
- data/spec/mongomodel/concerns/attribute_methods/protected_spec.rb +86 -0
- data/spec/mongomodel/concerns/attribute_methods/query_spec.rb +27 -0
- data/spec/mongomodel/concerns/attribute_methods/read_spec.rb +52 -0
- data/spec/mongomodel/concerns/attribute_methods/write_spec.rb +43 -0
- data/spec/mongomodel/concerns/attributes_spec.rb +152 -0
- data/spec/mongomodel/concerns/callbacks_spec.rb +90 -0
- data/spec/mongomodel/concerns/logging_spec.rb +20 -0
- data/spec/mongomodel/concerns/pretty_inspect_spec.rb +68 -0
- data/spec/mongomodel/concerns/properties_spec.rb +29 -0
- data/spec/mongomodel/concerns/timestamps_spec.rb +170 -0
- data/spec/mongomodel/concerns/validations_spec.rb +159 -0
- data/spec/mongomodel/document/callbacks_spec.rb +80 -0
- data/spec/mongomodel/document/dynamic_finders_spec.rb +183 -0
- data/spec/mongomodel/document/finders_spec.rb +231 -0
- data/spec/mongomodel/document/indexes_spec.rb +121 -0
- data/spec/mongomodel/document/optimistic_locking_spec.rb +57 -0
- data/spec/mongomodel/document/persistence_spec.rb +319 -0
- data/spec/mongomodel/document/scopes_spec.rb +204 -0
- data/spec/mongomodel/document/validations/uniqueness_spec.rb +217 -0
- data/spec/mongomodel/document/validations_spec.rb +132 -0
- data/spec/mongomodel/document_spec.rb +74 -0
- data/spec/mongomodel/embedded_document_spec.rb +66 -0
- data/spec/mongomodel/mongomodel_spec.rb +33 -0
- data/spec/mongomodel/support/collection_spec.rb +248 -0
- data/spec/mongomodel/support/mongo_options_spec.rb +295 -0
- data/spec/mongomodel/support/property_spec.rb +83 -0
- data/spec/spec.opts +6 -0
- data/spec/spec_helper.rb +21 -0
- data/spec/specdoc.opts +6 -0
- data/spec/support/callbacks.rb +44 -0
- data/spec/support/helpers/define_class.rb +24 -0
- data/spec/support/helpers/specs_for.rb +11 -0
- data/spec/support/matchers/be_a_subclass_of.rb +5 -0
- data/spec/support/matchers/respond_to_boolean.rb +17 -0
- data/spec/support/matchers/run_callbacks.rb +20 -0
- data/spec/support/models.rb +23 -0
- data/spec/support/time.rb +6 -0
- metadata +232 -0
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module MongoModel
|
|
4
|
+
specs_for(Document) do
|
|
5
|
+
describe "callbacks" do
|
|
6
|
+
define_class(:CallbackTestDocument, Document) do
|
|
7
|
+
include MongoModel::CallbackHelpers
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
let(:doc) { CallbackTestDocument.create! }
|
|
11
|
+
|
|
12
|
+
it "should run each type of callback when initializing" do
|
|
13
|
+
instance = CallbackTestDocument.new
|
|
14
|
+
instance.should run_callbacks(:after_initialize)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "should run each type of callback on find" do
|
|
18
|
+
instance = CallbackTestDocument.find(doc.id)
|
|
19
|
+
instance.should run_callbacks(:after_initialize, :after_find)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it "should run each type of callback when validating a new document" do
|
|
23
|
+
instance = CallbackTestDocument.new
|
|
24
|
+
instance.valid?
|
|
25
|
+
instance.should run_callbacks(:after_initialize, :before_validation, :after_validation)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it "should run each type of callback when validating an existing document" do
|
|
29
|
+
instance = CallbackTestDocument.find(doc.id)
|
|
30
|
+
instance.valid?
|
|
31
|
+
instance.should run_callbacks(:after_initialize, :after_find, :before_validation, :after_validation)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it "should run each type of callback when creating a document" do
|
|
35
|
+
instance = CallbackTestDocument.create!
|
|
36
|
+
instance.should run_callbacks(:after_initialize, :before_validation, :after_validation, :before_save, :before_create, :after_create, :after_save)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it "should run each type of callback when saving an existing document" do
|
|
40
|
+
instance = CallbackTestDocument.find(doc.id)
|
|
41
|
+
instance.save
|
|
42
|
+
instance.should run_callbacks(:after_initialize, :after_find, :before_validation, :after_validation, :before_save, :before_update, :after_update, :after_save)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it "should run each type of callback when destroying a document" do
|
|
46
|
+
instance = CallbackTestDocument.find(doc.id)
|
|
47
|
+
instance.destroy
|
|
48
|
+
instance.should run_callbacks(:after_initialize, :after_find, :before_destroy, :after_destroy)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it "should not run destroy callbacks when deleting a document" do
|
|
52
|
+
instance = CallbackTestDocument.find(doc.id)
|
|
53
|
+
instance.delete
|
|
54
|
+
instance.should run_callbacks(:after_initialize, :after_find)
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
[ :before_save, :before_create ].each do |callback|
|
|
59
|
+
context "#{callback} callback return false" do
|
|
60
|
+
define_class(:CallbackTestDocument, Document) do
|
|
61
|
+
send(callback) { false }
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
subject { CallbackTestDocument.new }
|
|
65
|
+
|
|
66
|
+
describe "#save" do
|
|
67
|
+
it "should return false" do
|
|
68
|
+
subject.save.should be_false
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
describe "#save!" do
|
|
73
|
+
it "should raise a MongoModel::DocumentNotSaved exception" do
|
|
74
|
+
lambda { subject.save! }.should raise_error(MongoModel::DocumentNotSaved)
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module MongoModel
|
|
4
|
+
specs_for(Document) do
|
|
5
|
+
describe "dynamic finders" do
|
|
6
|
+
define_class(:Person, Document) do
|
|
7
|
+
property :name, String
|
|
8
|
+
property :age, Integer
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
subject { Person }
|
|
12
|
+
|
|
13
|
+
before(:each) do
|
|
14
|
+
@john = Person.create!(:name => 'John', :age => 42, :id => '1')
|
|
15
|
+
@young_john = Person.create!(:name => 'John', :age => 12, :id => '2')
|
|
16
|
+
@tom1 = Person.create!(:name => 'Tom', :age => 23, :id => '3')
|
|
17
|
+
@tom2 = Person.create!(:name => 'Tom', :age => 23, :id => '4')
|
|
18
|
+
@mary = Person.create!(:name => 'Mary', :age => 33, :id => '5')
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
shared_examples_for "a dynamic finder" do
|
|
22
|
+
it { should respond_to(valid_finder) }
|
|
23
|
+
it { should_not respond_to(invalid_finder) }
|
|
24
|
+
|
|
25
|
+
it "should raise NoMethodError calling an invalid finder" do
|
|
26
|
+
lambda { subject.send(invalid_finder, "Foo") }.should raise_error(NoMethodError)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def self.should_find(*args, &block)
|
|
30
|
+
it "should return correct results when called with #{args.inspect}" do
|
|
31
|
+
expected = instance_eval(&block)
|
|
32
|
+
subject.send(valid_finder, *args).should == expected
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def self.should_raise(*args, &block)
|
|
37
|
+
it "should raise DocumentNotFound exception if results not found" do
|
|
38
|
+
message = instance_eval(&block)
|
|
39
|
+
lambda { subject.send(valid_finder, *args) }.should raise_error(DocumentNotFound, message)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def self.should_initialize(*args, &block)
|
|
44
|
+
it "should initialize new instance" do
|
|
45
|
+
result = subject.send(valid_finder, *args)
|
|
46
|
+
result.should be_a_new_record
|
|
47
|
+
result.should be_an_instance_of(Person)
|
|
48
|
+
yield(result).should be_true
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def self.should_create(*args, &block)
|
|
53
|
+
it "should create new instance" do
|
|
54
|
+
result = subject.send(valid_finder, *args)
|
|
55
|
+
result.should_not be_a_new_record
|
|
56
|
+
result.should be_an_instance_of(Person)
|
|
57
|
+
yield(result).should be_true
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
describe "find first by single property" do
|
|
63
|
+
let(:valid_finder) { :find_by_name }
|
|
64
|
+
let(:invalid_finder) { :find_by_something_else }
|
|
65
|
+
|
|
66
|
+
it_should_behave_like "a dynamic finder"
|
|
67
|
+
|
|
68
|
+
should_find("John") { @john }
|
|
69
|
+
should_find("John", :conditions => { :age.lt => 20 }) { @young_john }
|
|
70
|
+
should_find("Jane") { nil }
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
describe "find first by single property (bang method)" do
|
|
74
|
+
let(:valid_finder) { :find_by_name! }
|
|
75
|
+
let(:invalid_finder) { :find_by_something_else! }
|
|
76
|
+
|
|
77
|
+
it_should_behave_like "a dynamic finder"
|
|
78
|
+
|
|
79
|
+
should_find("John") { @john }
|
|
80
|
+
should_raise("Jane") { 'Couldn\'t find Person with {:name=>"Jane"}' }
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
describe "find last by single property" do
|
|
84
|
+
let(:valid_finder) { :find_last_by_name }
|
|
85
|
+
let(:invalid_finder) { :find_last_by_something_else }
|
|
86
|
+
|
|
87
|
+
it_should_behave_like "a dynamic finder"
|
|
88
|
+
|
|
89
|
+
should_find("John") { @young_john }
|
|
90
|
+
should_find("Jane") { nil }
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
describe "find all by single property" do
|
|
94
|
+
let(:valid_finder) { :find_all_by_name }
|
|
95
|
+
let(:invalid_finder) { :find_all_by_something_else }
|
|
96
|
+
|
|
97
|
+
it_should_behave_like "a dynamic finder"
|
|
98
|
+
|
|
99
|
+
should_find("John") { [@john, @young_john] }
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
describe "find first by multiple properties" do
|
|
103
|
+
let(:valid_finder) { :find_by_name_and_age }
|
|
104
|
+
let(:invalid_finder) { :find_by_age_and_something_else }
|
|
105
|
+
|
|
106
|
+
it_should_behave_like "a dynamic finder"
|
|
107
|
+
|
|
108
|
+
should_find("Tom", 23) { @tom1 }
|
|
109
|
+
should_find("Tom", 5) { nil }
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
describe "find first by multiple properties (bang method)" do
|
|
113
|
+
let(:valid_finder) { :find_by_name_and_age! }
|
|
114
|
+
let(:invalid_finder) { :find_by_age_and_something_else! }
|
|
115
|
+
|
|
116
|
+
it_should_behave_like "a dynamic finder"
|
|
117
|
+
|
|
118
|
+
should_find("Tom", 23) { @tom1 }
|
|
119
|
+
should_raise("Tom", 5) { "Couldn\'t find Person with #{{:name=>"Tom", :age=>5}.inspect}" }
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
describe "find all by multiple properties" do
|
|
123
|
+
let(:valid_finder) { :find_all_by_name_and_age }
|
|
124
|
+
let(:invalid_finder) { :find_all_by_age_and_something_else }
|
|
125
|
+
|
|
126
|
+
it_should_behave_like "a dynamic finder"
|
|
127
|
+
|
|
128
|
+
should_find("Tom", 23) { [@tom1, @tom2] }
|
|
129
|
+
should_find("Tom", 5) { [] }
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
describe "find last by multiple properties" do
|
|
133
|
+
let(:valid_finder) { :find_last_by_name_and_age }
|
|
134
|
+
let(:invalid_finder) { :find_last_by_age_and_something_else }
|
|
135
|
+
|
|
136
|
+
it_should_behave_like "a dynamic finder"
|
|
137
|
+
|
|
138
|
+
should_find("Tom", 23) { @tom2 }
|
|
139
|
+
should_find("Tom", 5) { nil }
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
describe "find or initialize by single property" do
|
|
143
|
+
let(:valid_finder) { :find_or_initialize_by_name }
|
|
144
|
+
let(:invalid_finder) { :find_or_initialize_by_something_else }
|
|
145
|
+
|
|
146
|
+
it_should_behave_like "a dynamic finder"
|
|
147
|
+
|
|
148
|
+
should_find("John") { @john }
|
|
149
|
+
should_initialize("Jane") { |p| p.name == "Jane" }
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
describe "find or initialize by multiple properties" do
|
|
153
|
+
let(:valid_finder) { :find_or_initialize_by_name_and_age }
|
|
154
|
+
let(:invalid_finder) { :find_or_initialize_by_name_and_something_else }
|
|
155
|
+
|
|
156
|
+
it_should_behave_like "a dynamic finder"
|
|
157
|
+
|
|
158
|
+
should_find("John", 42) { @john }
|
|
159
|
+
should_initialize("John", 1) { |p| p.name == "John" && p.age == 1 }
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
describe "find or create by single property" do
|
|
163
|
+
let(:valid_finder) { :find_or_create_by_name }
|
|
164
|
+
let(:invalid_finder) { :find_or_create_by_something_else }
|
|
165
|
+
|
|
166
|
+
it_should_behave_like "a dynamic finder"
|
|
167
|
+
|
|
168
|
+
should_find("John") { @john }
|
|
169
|
+
should_create("Jane") { |p| p.name == "Jane" }
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
describe "find or create by multiple properties" do
|
|
173
|
+
let(:valid_finder) { :find_or_create_by_name_and_age }
|
|
174
|
+
let(:invalid_finder) { :find_or_create_by_name_and_something_else }
|
|
175
|
+
|
|
176
|
+
it_should_behave_like "a dynamic finder"
|
|
177
|
+
|
|
178
|
+
should_find("John", 42) { @john }
|
|
179
|
+
should_create("John", 1) { |p| p.name == "John" && p.age == 1 }
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
end
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module MongoModel
|
|
4
|
+
describe Document do
|
|
5
|
+
define_class(:User, Document) do
|
|
6
|
+
property :name, String
|
|
7
|
+
property :age, Integer
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
define_class(:NonUser, Document)
|
|
11
|
+
|
|
12
|
+
describe "#find" do
|
|
13
|
+
before(:each) do
|
|
14
|
+
User.collection.save({ '_id' => '1', 'name' => 'Fred', :age => 45 })
|
|
15
|
+
User.collection.save({ '_id' => '2', 'name' => 'Alistair', :age => 18 })
|
|
16
|
+
User.collection.save({ '_id' => '3', 'name' => 'Barney', :age => 10 })
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
describe "by id" do
|
|
20
|
+
context "document exists" do
|
|
21
|
+
subject { User.find('2') }
|
|
22
|
+
|
|
23
|
+
it "should return a User" do
|
|
24
|
+
subject.should be_a(User)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it "should load the document attributes" do
|
|
28
|
+
subject.id.should == '2'
|
|
29
|
+
subject.name.should == 'Alistair'
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it { should_not be_a_new_record }
|
|
33
|
+
|
|
34
|
+
it "should stringify ids" do
|
|
35
|
+
User.find(2).id.should == '2'
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
context "document does not exist" do
|
|
40
|
+
it "should raise a DocumentNotFound exception" do
|
|
41
|
+
lambda {
|
|
42
|
+
User.find('4')
|
|
43
|
+
}.should raise_error(MongoModel::DocumentNotFound)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
context "no id specified" do
|
|
48
|
+
it "should raise an ArgumentError" do
|
|
49
|
+
lambda {
|
|
50
|
+
User.find
|
|
51
|
+
}.should raise_error(ArgumentError)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
describe "by multiple ids" do
|
|
57
|
+
context "all documents exist" do
|
|
58
|
+
subject { User.find('1', '2') }
|
|
59
|
+
|
|
60
|
+
it "should return an array of Users" do
|
|
61
|
+
subject[0].should be_a(User)
|
|
62
|
+
subject[1].should be_a(User)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
it "should load document attributes" do
|
|
66
|
+
subject[0].name.should == 'Fred'
|
|
67
|
+
subject[1].name.should == 'Alistair'
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
it "should load documents in correct order" do
|
|
71
|
+
result = User.find('2', '1')
|
|
72
|
+
result[0].id.should == '2'
|
|
73
|
+
result[1].id.should == '1'
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
context "some documents missing" do
|
|
78
|
+
it "should raise a DocumentNotFound exception" do
|
|
79
|
+
lambda {
|
|
80
|
+
User.find('1', '2', '4')
|
|
81
|
+
}.should raise_error(MongoModel::DocumentNotFound)
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
describe "first" do
|
|
87
|
+
context "documents exist" do
|
|
88
|
+
subject { User.find(:first) }
|
|
89
|
+
|
|
90
|
+
it "should return the first document" do
|
|
91
|
+
subject.id.should == '1'
|
|
92
|
+
subject.name.should == 'Fred'
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
it "should be aliased as #first" do
|
|
96
|
+
User.first.should == subject
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
context "with order" do
|
|
100
|
+
it "should find first document by order" do
|
|
101
|
+
User.find(:first, :order => :name.asc).name.should == 'Alistair'
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
context "no documents" do
|
|
107
|
+
before(:each) { User.collection.remove }
|
|
108
|
+
|
|
109
|
+
it "should return nil" do
|
|
110
|
+
User.find(:first).should be_nil
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
describe "last" do
|
|
116
|
+
context "documents exist" do
|
|
117
|
+
subject { User.find(:last) }
|
|
118
|
+
|
|
119
|
+
it "should return the last document (by id)" do
|
|
120
|
+
subject.id.should == '3'
|
|
121
|
+
subject.name.should == 'Barney'
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
it "should be aliased as #last" do
|
|
125
|
+
User.last.should == subject
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
context "with order" do
|
|
129
|
+
it "should find last document by order" do
|
|
130
|
+
User.find(:last, :order => :name.asc).name.should == 'Fred'
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
context "no documents" do
|
|
136
|
+
before(:each) { User.collection.remove }
|
|
137
|
+
|
|
138
|
+
it "should return nil" do
|
|
139
|
+
User.find(:last).should be_nil
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
describe "all" do
|
|
145
|
+
subject { User.find(:all, :order => 'id ASC') }
|
|
146
|
+
|
|
147
|
+
it "should return all documents as User instances" do
|
|
148
|
+
subject.should have(3).users
|
|
149
|
+
subject.each { |d| d.should be_a(User) }
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
it "should load attributes for each document" do
|
|
153
|
+
subject[0].name.should == 'Fred'
|
|
154
|
+
subject[1].name.should == 'Alistair'
|
|
155
|
+
subject[2].name.should == 'Barney'
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
it "should be aliased as #all" do
|
|
159
|
+
User.all.should == subject
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
context "with exact-match conditions" do
|
|
163
|
+
subject { User.find(:all, :conditions => { :name => 'Alistair' }) }
|
|
164
|
+
|
|
165
|
+
it "should only return documents matching conditions" do
|
|
166
|
+
subject.should have(1).user
|
|
167
|
+
subject[0].name.should == 'Alistair'
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
context "with inequality conditions" do
|
|
172
|
+
subject { User.find(:all, :conditions => { :age.lt => 21 }) }
|
|
173
|
+
|
|
174
|
+
it "should only return documents matching conditions" do
|
|
175
|
+
subject.should have(2).users
|
|
176
|
+
subject[0].name.should == 'Alistair'
|
|
177
|
+
subject[1].name.should == 'Barney'
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
describe "#count" do
|
|
184
|
+
before(:each) do
|
|
185
|
+
5.times { User.create(:age => 18) }
|
|
186
|
+
7.times { User.create(:age => 42) }
|
|
187
|
+
3.times { NonUser.create }
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
context "without arguments" do
|
|
191
|
+
it "should return the count for that particular model" do
|
|
192
|
+
User.count.should == 12
|
|
193
|
+
NonUser.count.should == 3
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
context "with conditions" do
|
|
198
|
+
it "should return the count for the model that match the conditions" do
|
|
199
|
+
User.count(:age => 18).should == 5
|
|
200
|
+
User.count(:age.gte => 18).should == 12
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
describe "#exists?" do
|
|
206
|
+
before(:each) do
|
|
207
|
+
User.create(:id => 'user-1', :name => 'Test', :age => 10)
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
context "by id" do
|
|
211
|
+
it "should return true if the document exists" do
|
|
212
|
+
User.exists?('user-1').should == true
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
it "should return false if the document does not exist" do
|
|
216
|
+
User.exists?('user-2').should == false
|
|
217
|
+
end
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
context "by conditions" do
|
|
221
|
+
it "should return true if the document exists" do
|
|
222
|
+
User.exists?(:name => 'Test').should == true
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
it "should return false if the document does not exist" do
|
|
226
|
+
User.exists?(:name => 'Nonexistant').should == false
|
|
227
|
+
end
|
|
228
|
+
end
|
|
229
|
+
end
|
|
230
|
+
end
|
|
231
|
+
end
|