mongoid 1.1.4 → 1.2.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/HISTORY +69 -1
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/lib/mongoid.rb +39 -13
- data/lib/mongoid/associations.rb +1 -0
- data/lib/mongoid/associations/has_many.rb +19 -3
- data/lib/mongoid/attributes.rb +6 -1
- data/lib/mongoid/collection.rb +106 -0
- data/lib/mongoid/collections/cyclic_iterator.rb +34 -0
- data/lib/mongoid/collections/master.rb +28 -0
- data/lib/mongoid/collections/mimic.rb +46 -0
- data/lib/mongoid/collections/operations.rb +39 -0
- data/lib/mongoid/collections/slaves.rb +44 -0
- data/lib/mongoid/commands.rb +1 -0
- data/lib/mongoid/config.rb +61 -9
- data/lib/mongoid/contexts/enumerable.rb +24 -15
- data/lib/mongoid/contexts/mongo.rb +25 -31
- data/lib/mongoid/contexts/paging.rb +2 -2
- data/lib/mongoid/criteria.rb +48 -7
- data/lib/mongoid/criterion/exclusion.rb +2 -0
- data/lib/mongoid/criterion/optional.rb +2 -2
- data/lib/mongoid/cursor.rb +82 -0
- data/lib/mongoid/document.rb +12 -13
- data/lib/mongoid/errors.rb +35 -4
- data/lib/mongoid/extensions.rb +1 -0
- data/lib/mongoid/extensions/array/aliasing.rb +4 -0
- data/lib/mongoid/extensions/string/inflections.rb +44 -1
- data/lib/mongoid/factory.rb +17 -0
- data/lib/mongoid/finders.rb +7 -2
- data/lib/mongoid/matchers/default.rb +6 -0
- data/lib/mongoid/matchers/gt.rb +1 -1
- data/lib/mongoid/matchers/gte.rb +1 -1
- data/lib/mongoid/matchers/lt.rb +1 -1
- data/lib/mongoid/matchers/lte.rb +1 -1
- data/mongoid.gemspec +30 -5
- data/perf/benchmark.rb +5 -3
- data/spec/integration/mongoid/associations_spec.rb +12 -0
- data/spec/integration/mongoid/contexts/enumerable_spec.rb +20 -0
- data/spec/integration/mongoid/criteria_spec.rb +28 -0
- data/spec/integration/mongoid/document_spec.rb +1 -1
- data/spec/integration/mongoid/inheritance_spec.rb +2 -2
- data/spec/models/person.rb +1 -1
- data/spec/spec_helper.rb +9 -4
- data/spec/unit/mongoid/associations/has_many_spec.rb +19 -0
- data/spec/unit/mongoid/associations_spec.rb +9 -0
- data/spec/unit/mongoid/attributes_spec.rb +4 -4
- data/spec/unit/mongoid/collection_spec.rb +113 -0
- data/spec/unit/mongoid/collections/cyclic_iterator_spec.rb +75 -0
- data/spec/unit/mongoid/collections/master_spec.rb +41 -0
- data/spec/unit/mongoid/collections/mimic_spec.rb +43 -0
- data/spec/unit/mongoid/collections/slaves_spec.rb +81 -0
- data/spec/unit/mongoid/commands_spec.rb +7 -0
- data/spec/unit/mongoid/config_spec.rb +52 -1
- data/spec/unit/mongoid/contexts/enumerable_spec.rb +38 -12
- data/spec/unit/mongoid/contexts/mongo_spec.rb +38 -31
- data/spec/unit/mongoid/criteria_spec.rb +20 -12
- data/spec/unit/mongoid/criterion/exclusion_spec.rb +26 -0
- data/spec/unit/mongoid/criterion/optional_spec.rb +13 -0
- data/spec/unit/mongoid/cursor_spec.rb +74 -0
- data/spec/unit/mongoid/document_spec.rb +4 -5
- data/spec/unit/mongoid/errors_spec.rb +5 -9
- data/spec/unit/mongoid/extensions/string/inflections_spec.rb +21 -2
- data/spec/unit/mongoid/factory_spec.rb +16 -0
- data/spec/unit/mongoid_spec.rb +4 -4
- metadata +28 -3
data/perf/benchmark.rb
CHANGED
@@ -3,10 +3,12 @@ require "ruby-prof"
|
|
3
3
|
require "benchmark"
|
4
4
|
require "mongoid"
|
5
5
|
|
6
|
-
|
7
|
-
|
6
|
+
Mongoid.configure do |config|
|
7
|
+
config.persist_in_safe_mode = false
|
8
|
+
config.master = Mongo::Connection.new.db("mongoid_perf_test")
|
9
|
+
end
|
8
10
|
|
9
|
-
Mongoid.
|
11
|
+
Mongoid.master.collection("people").drop
|
10
12
|
|
11
13
|
class Person
|
12
14
|
include Mongoid::Document
|
@@ -118,6 +118,18 @@ describe Mongoid::Associations do
|
|
118
118
|
from_db.posts.should == [@post]
|
119
119
|
end
|
120
120
|
|
121
|
+
context "when adding a new association" do
|
122
|
+
|
123
|
+
before do
|
124
|
+
@new_post = Post.new(:title => "New")
|
125
|
+
@person.posts << @new_post
|
126
|
+
end
|
127
|
+
|
128
|
+
it "rememoizes the new association" do
|
129
|
+
@person.posts.should == [ @post, @new_post ]
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
121
133
|
context "when building" do
|
122
134
|
|
123
135
|
before do
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Mongoid::Contexts::Enumerable do
|
4
|
+
|
5
|
+
before do
|
6
|
+
@person = Person.new(:title => "Sir")
|
7
|
+
10.times do |n|
|
8
|
+
@person.addresses << Address.new(:number => n, :street => "Upper Street")
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "#paginate" do
|
13
|
+
|
14
|
+
it "paginates the embedded documents" do
|
15
|
+
addresses = @person.addresses.paginate(:page => nil, :per_page => 5)
|
16
|
+
addresses.current_page.should == 1
|
17
|
+
addresses.size.should == 5
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -2,6 +2,34 @@ require "spec_helper"
|
|
2
2
|
|
3
3
|
describe Mongoid::Criteria do
|
4
4
|
|
5
|
+
describe "#excludes" do
|
6
|
+
|
7
|
+
before do
|
8
|
+
@person = Person.create(:title => "Sir", :age => 100, :aliases => ["D", "Durran"], :ssn => "666666666")
|
9
|
+
end
|
10
|
+
|
11
|
+
after do
|
12
|
+
Person.delete_all
|
13
|
+
end
|
14
|
+
|
15
|
+
context "when passed id" do
|
16
|
+
|
17
|
+
it "it properly excludes ids" do
|
18
|
+
Person.criteria.excludes(:id => @person.id).entries.should be_empty
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
context "when passed _id" do
|
24
|
+
|
25
|
+
it "it properly excludes ids" do
|
26
|
+
Person.criteria.excludes(:_id => @person.id).entries.should be_empty
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
5
33
|
describe "#max" do
|
6
34
|
|
7
35
|
before do
|
@@ -16,7 +16,7 @@ describe Mongoid::Document do
|
|
16
16
|
end
|
17
17
|
|
18
18
|
it "saves in the same collection as the root" do
|
19
|
-
collection = Mongoid.
|
19
|
+
collection = Mongoid.master.collection("canvases")
|
20
20
|
attributes = collection.find({ :name => "Test"}, {}).next_document
|
21
21
|
attributes["version"].should == 3
|
22
22
|
attributes["name"].should == "Test"
|
@@ -34,7 +34,7 @@ describe Mongoid::Document do
|
|
34
34
|
end
|
35
35
|
|
36
36
|
it "saves in the same collection as the root" do
|
37
|
-
collection = Mongoid.
|
37
|
+
collection = Mongoid.master.collection("canvases")
|
38
38
|
attributes = collection.find({ :name => "Testy"}, {}).next_document
|
39
39
|
attributes["version"].should == 2
|
40
40
|
attributes["name"].should == "Testy"
|
data/spec/models/person.rb
CHANGED
data/spec/spec_helper.rb
CHANGED
@@ -12,15 +12,20 @@ require "mocha"
|
|
12
12
|
require "mongoid"
|
13
13
|
require "spec"
|
14
14
|
|
15
|
-
Mongoid.
|
16
|
-
|
15
|
+
Mongoid.configure do |config|
|
16
|
+
name = "mongoid_test"
|
17
|
+
host = "localhost"
|
18
|
+
config.master = Mongo::Connection.new.db(name)
|
19
|
+
# config.slaves = [
|
20
|
+
# Mongo::Connection.new(host, 27018, :slave_ok => true).db(name)
|
21
|
+
# ]
|
17
22
|
end
|
18
23
|
|
19
|
-
Dir[File.join(MODELS, "*.rb")].each {|file| require File.basename(file) }
|
24
|
+
Dir[ File.join(MODELS, "*.rb") ].sort.each { |file| require File.basename(file) }
|
20
25
|
|
21
26
|
Spec::Runner.configure do |config|
|
22
27
|
config.mock_with :mocha
|
23
28
|
config.after :suite do
|
24
|
-
Mongoid.
|
29
|
+
Mongoid.master.collections.each(&:drop)
|
25
30
|
end
|
26
31
|
end
|
@@ -399,6 +399,25 @@ describe Mongoid::Associations::HasMany do
|
|
399
399
|
|
400
400
|
end
|
401
401
|
|
402
|
+
describe "#paginate" do
|
403
|
+
|
404
|
+
before do
|
405
|
+
@association = Mongoid::Associations::HasMany.new(
|
406
|
+
@document,
|
407
|
+
Mongoid::Associations::Options.new(:name => :addresses)
|
408
|
+
)
|
409
|
+
@options = { :page => 1, :per_page => 10 }
|
410
|
+
@criteria = mock
|
411
|
+
end
|
412
|
+
|
413
|
+
it "creates a criteria and paginates it" do
|
414
|
+
Mongoid::Criteria.expects(:translate).with(Address, @options).returns(@criteria)
|
415
|
+
@criteria.expects(:documents=).with(@association.target)
|
416
|
+
@criteria.expects(:paginate).returns([])
|
417
|
+
@association.paginate(@options).should == []
|
418
|
+
end
|
419
|
+
end
|
420
|
+
|
402
421
|
describe "#push" do
|
403
422
|
|
404
423
|
before do
|
@@ -417,6 +417,15 @@ describe Mongoid::Associations do
|
|
417
417
|
@game.should respond_to(:person)
|
418
418
|
end
|
419
419
|
|
420
|
+
context "when document is root level" do
|
421
|
+
|
422
|
+
it "puts an index on the foreign key" do
|
423
|
+
Game.expects(:index).with("person_id")
|
424
|
+
Game.belongs_to_related :person
|
425
|
+
end
|
426
|
+
|
427
|
+
end
|
428
|
+
|
420
429
|
end
|
421
430
|
|
422
431
|
describe ".has_one_related" do
|
@@ -118,7 +118,7 @@ describe Mongoid::Attributes do
|
|
118
118
|
describe "#method_missing" do
|
119
119
|
|
120
120
|
before do
|
121
|
-
Mongoid.allow_dynamic_fields = true
|
121
|
+
Mongoid.configure.allow_dynamic_fields = true
|
122
122
|
@attributes = {
|
123
123
|
:testing => "Testing"
|
124
124
|
}
|
@@ -155,7 +155,7 @@ describe Mongoid::Attributes do
|
|
155
155
|
context "when allowing dynamic fields" do
|
156
156
|
|
157
157
|
before do
|
158
|
-
Mongoid.allow_dynamic_fields = true
|
158
|
+
Mongoid.configure.allow_dynamic_fields = true
|
159
159
|
@person = Person.new(@attributes)
|
160
160
|
end
|
161
161
|
|
@@ -180,7 +180,7 @@ describe Mongoid::Attributes do
|
|
180
180
|
context "when not allowing dynamic fields" do
|
181
181
|
|
182
182
|
before do
|
183
|
-
Mongoid.allow_dynamic_fields = false
|
183
|
+
Mongoid.configure.allow_dynamic_fields = false
|
184
184
|
Person.fields.delete(:nofieldstring)
|
185
185
|
@attributes = {
|
186
186
|
:nofieldstring => "Testing"
|
@@ -188,7 +188,7 @@ describe Mongoid::Attributes do
|
|
188
188
|
end
|
189
189
|
|
190
190
|
after do
|
191
|
-
Mongoid.allow_dynamic_fields = true
|
191
|
+
Mongoid.configure.allow_dynamic_fields = true
|
192
192
|
end
|
193
193
|
|
194
194
|
it "raises an error" do
|
@@ -0,0 +1,113 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Mongoid::Collection do
|
4
|
+
|
5
|
+
let(:master) do
|
6
|
+
stub.quacks_like(Mongoid::Collections::Master.allocate)
|
7
|
+
end
|
8
|
+
|
9
|
+
let(:slaves) do
|
10
|
+
stub.quacks_like(Mongoid::Collections::Slaves.allocate)
|
11
|
+
end
|
12
|
+
|
13
|
+
let(:collection) do
|
14
|
+
Mongoid::Collection.new("people")
|
15
|
+
end
|
16
|
+
|
17
|
+
before do
|
18
|
+
collection.instance_variable_set(:@master, master)
|
19
|
+
collection.instance_variable_set(:@slaves, slaves)
|
20
|
+
end
|
21
|
+
|
22
|
+
context "Mongo::Collection write operations" do
|
23
|
+
|
24
|
+
Mongoid::Collections::Operations::WRITE.each do |name|
|
25
|
+
|
26
|
+
it "defines #{name}" do
|
27
|
+
collection.should respond_to(name)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
context "Mongo::Collection read operations" do
|
34
|
+
|
35
|
+
Mongoid::Collections::Operations::READ.each do |name|
|
36
|
+
|
37
|
+
it "defines #{name}" do
|
38
|
+
collection.should respond_to(name)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe "#directed" do
|
44
|
+
|
45
|
+
context "when the counter is less than the maximum" do
|
46
|
+
|
47
|
+
before do
|
48
|
+
collection.instance_variable_set(:@counter, 0)
|
49
|
+
end
|
50
|
+
|
51
|
+
it "delegates to the master" do
|
52
|
+
collection.directed.should == master
|
53
|
+
end
|
54
|
+
|
55
|
+
it "increments the counter" do
|
56
|
+
collection.directed
|
57
|
+
collection.counter.should == 1
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
context "when the counter is at the max" do
|
62
|
+
|
63
|
+
before do
|
64
|
+
slaves.expects(:empty?).returns(false)
|
65
|
+
collection.instance_variable_set(:@counter, 10)
|
66
|
+
end
|
67
|
+
|
68
|
+
it "delegates to the slave" do
|
69
|
+
collection.directed.should == slaves
|
70
|
+
end
|
71
|
+
|
72
|
+
it "resets the counter" do
|
73
|
+
collection.directed
|
74
|
+
collection.counter.should == 0
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
context "when the slave does not exist" do
|
79
|
+
|
80
|
+
before do
|
81
|
+
collection.instance_variable_set(:@counter, 10)
|
82
|
+
slaves.expects(:empty?).returns(true)
|
83
|
+
end
|
84
|
+
|
85
|
+
it "delegates to the master" do
|
86
|
+
collection.directed.should == master
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
describe "#find" do
|
92
|
+
|
93
|
+
before do
|
94
|
+
@cursor = stub.quacks_like(Mongoid::Cursor.allocate)
|
95
|
+
master.expects(:find).with({ :test => "value" }, {}).returns(@mongo_cursor)
|
96
|
+
Mongoid::Cursor.expects(:new).with(collection, @mongo_cursor).returns(@cursor)
|
97
|
+
end
|
98
|
+
|
99
|
+
it "finds are returns a cursor" do
|
100
|
+
collection.find({ :test => "value"}).should == @cursor
|
101
|
+
end
|
102
|
+
|
103
|
+
context "when a block is supplied" do
|
104
|
+
|
105
|
+
it "yields to the cursor and closes it" do
|
106
|
+
@cursor.expects(:close).returns(true)
|
107
|
+
collection.find({ :test => "value" }) do |cur|
|
108
|
+
cur.should == @cursor
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Mongoid::Collections::CyclicIterator do
|
4
|
+
|
5
|
+
before do
|
6
|
+
@first = stub
|
7
|
+
@second = stub
|
8
|
+
@third = stub
|
9
|
+
@fourth = stub
|
10
|
+
end
|
11
|
+
|
12
|
+
let(:array) do
|
13
|
+
[ @first, @second, @third, @fourth ]
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "#initialize" do
|
17
|
+
|
18
|
+
let(:iterator) do
|
19
|
+
Mongoid::Collections::CyclicIterator.new(array)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "defaults the counter to -1" do
|
23
|
+
iterator.counter.should == -1
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "#next" do
|
28
|
+
|
29
|
+
context "when the iterator has just been created" do
|
30
|
+
|
31
|
+
let(:iterator) do
|
32
|
+
Mongoid::Collections::CyclicIterator.new(array)
|
33
|
+
end
|
34
|
+
|
35
|
+
it "returns the first element" do
|
36
|
+
iterator.next.should == @first
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
context "when the iterator is in the middle" do
|
41
|
+
|
42
|
+
let(:iterator) do
|
43
|
+
Mongoid::Collections::CyclicIterator.new(array)
|
44
|
+
end
|
45
|
+
|
46
|
+
before do
|
47
|
+
2.times { iterator.next }
|
48
|
+
end
|
49
|
+
|
50
|
+
it "returns the next element given the index" do
|
51
|
+
iterator.next.should == @third
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
context "when the iterator is on the last element" do
|
56
|
+
|
57
|
+
let(:iterator) do
|
58
|
+
Mongoid::Collections::CyclicIterator.new(array)
|
59
|
+
end
|
60
|
+
|
61
|
+
before do
|
62
|
+
4.times { iterator.next }
|
63
|
+
end
|
64
|
+
|
65
|
+
it "returns the first element" do
|
66
|
+
iterator.next.should == @first
|
67
|
+
end
|
68
|
+
|
69
|
+
it "resets the counter" do
|
70
|
+
iterator.next
|
71
|
+
iterator.counter.should == 0
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Mongoid::Collections::Master do
|
4
|
+
|
5
|
+
let(:collection) do
|
6
|
+
stub.quacks_like(Mongo::Collection.allocate)
|
7
|
+
end
|
8
|
+
|
9
|
+
let(:db) do
|
10
|
+
stub.quacks_like(Mongo::DB.allocate)
|
11
|
+
end
|
12
|
+
|
13
|
+
let(:master) do
|
14
|
+
Mongoid::Collections::Master.new(db, "people")
|
15
|
+
end
|
16
|
+
|
17
|
+
before do
|
18
|
+
db.expects(:collection).with("people").returns(collection)
|
19
|
+
end
|
20
|
+
|
21
|
+
context "Mongo::Collection operations" do
|
22
|
+
|
23
|
+
Mongoid::Collections::Operations::ALL.each do |name|
|
24
|
+
|
25
|
+
it "defines #{name}" do
|
26
|
+
master.should respond_to(name)
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "##{name}" do
|
30
|
+
|
31
|
+
before do
|
32
|
+
collection.expects(name)
|
33
|
+
end
|
34
|
+
|
35
|
+
it "delegates to the collection" do
|
36
|
+
master.send(name)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|