mongoid 1.0.6 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (79) hide show
  1. data/HISTORY +39 -0
  2. data/Rakefile +1 -1
  3. data/VERSION +1 -1
  4. data/lib/mongoid.rb +3 -1
  5. data/lib/mongoid/associations.rb +5 -5
  6. data/lib/mongoid/associations/has_many.rb +8 -2
  7. data/lib/mongoid/associations/has_many_related.rb +10 -4
  8. data/lib/mongoid/attributes.rb +19 -13
  9. data/lib/mongoid/commands.rb +12 -6
  10. data/lib/mongoid/commands/create.rb +2 -2
  11. data/lib/mongoid/commands/delete_all.rb +1 -1
  12. data/lib/mongoid/commands/save.rb +2 -2
  13. data/lib/mongoid/components.rb +1 -0
  14. data/lib/mongoid/contexts.rb +4 -0
  15. data/lib/mongoid/contexts/enumerable.rb +105 -0
  16. data/lib/mongoid/contexts/mongo.rb +228 -0
  17. data/lib/mongoid/contexts/paging.rb +42 -0
  18. data/lib/mongoid/criteria.rb +42 -191
  19. data/lib/mongoid/document.rb +19 -13
  20. data/lib/mongoid/extensions.rb +1 -0
  21. data/lib/mongoid/extensions/array/accessors.rb +3 -1
  22. data/lib/mongoid/extensions/float/conversions.rb +1 -1
  23. data/lib/mongoid/extensions/hash/accessors.rb +1 -1
  24. data/lib/mongoid/extensions/integer/conversions.rb +1 -0
  25. data/lib/mongoid/fields.rb +6 -5
  26. data/lib/mongoid/matchers.rb +36 -0
  27. data/lib/mongoid/matchers/all.rb +11 -0
  28. data/lib/mongoid/matchers/default.rb +20 -0
  29. data/lib/mongoid/matchers/exists.rb +13 -0
  30. data/lib/mongoid/matchers/gt.rb +11 -0
  31. data/lib/mongoid/matchers/gte.rb +11 -0
  32. data/lib/mongoid/matchers/in.rb +11 -0
  33. data/lib/mongoid/matchers/lt.rb +11 -0
  34. data/lib/mongoid/matchers/lte.rb +11 -0
  35. data/lib/mongoid/matchers/ne.rb +11 -0
  36. data/lib/mongoid/matchers/nin.rb +11 -0
  37. data/lib/mongoid/matchers/size.rb +11 -0
  38. data/lib/mongoid/scope.rb +17 -1
  39. data/mongoid.gemspec +51 -5
  40. data/spec/integration/mongoid/associations_spec.rb +67 -5
  41. data/spec/integration/mongoid/attributes_spec.rb +22 -0
  42. data/spec/integration/mongoid/commands_spec.rb +51 -12
  43. data/spec/integration/mongoid/criteria_spec.rb +3 -3
  44. data/spec/integration/mongoid/document_spec.rb +8 -8
  45. data/spec/integration/mongoid/finders_spec.rb +1 -1
  46. data/spec/integration/mongoid/inheritance_spec.rb +6 -0
  47. data/spec/integration/mongoid/named_scope_spec.rb +1 -1
  48. data/spec/spec_helper.rb +47 -6
  49. data/spec/unit/mongoid/associations/has_many_related_spec.rb +42 -0
  50. data/spec/unit/mongoid/associations/has_many_spec.rb +40 -1
  51. data/spec/unit/mongoid/attributes_spec.rb +1 -1
  52. data/spec/unit/mongoid/commands/create_spec.rb +3 -3
  53. data/spec/unit/mongoid/commands/delete_all_spec.rb +2 -2
  54. data/spec/unit/mongoid/commands/save_spec.rb +2 -2
  55. data/spec/unit/mongoid/commands_spec.rb +12 -12
  56. data/spec/unit/mongoid/contexts/enumerable_spec.rb +208 -0
  57. data/spec/unit/mongoid/contexts/mongo_spec.rb +370 -0
  58. data/spec/unit/mongoid/criteria_spec.rb +182 -21
  59. data/spec/unit/mongoid/extensions/array/accessors_spec.rb +9 -9
  60. data/spec/unit/mongoid/extensions/date/conversions_spec.rb +2 -1
  61. data/spec/unit/mongoid/extensions/float/conversions_spec.rb +4 -4
  62. data/spec/unit/mongoid/extensions/integer/conversions_spec.rb +1 -1
  63. data/spec/unit/mongoid/fields_spec.rb +3 -3
  64. data/spec/unit/mongoid/identity_spec.rb +2 -2
  65. data/spec/unit/mongoid/matchers/all_spec.rb +27 -0
  66. data/spec/unit/mongoid/matchers/default_spec.rb +27 -0
  67. data/spec/unit/mongoid/matchers/exists_spec.rb +56 -0
  68. data/spec/unit/mongoid/matchers/gt_spec.rb +39 -0
  69. data/spec/unit/mongoid/matchers/gte_spec.rb +49 -0
  70. data/spec/unit/mongoid/matchers/in_spec.rb +27 -0
  71. data/spec/unit/mongoid/matchers/lt_spec.rb +39 -0
  72. data/spec/unit/mongoid/matchers/lte_spec.rb +49 -0
  73. data/spec/unit/mongoid/matchers/ne_spec.rb +27 -0
  74. data/spec/unit/mongoid/matchers/nin_spec.rb +27 -0
  75. data/spec/unit/mongoid/matchers/size_spec.rb +27 -0
  76. data/spec/unit/mongoid/matchers_spec.rb +329 -0
  77. data/spec/unit/mongoid/scope_spec.rb +70 -0
  78. data/spec/unit/mongoid/timestamps_spec.rb +2 -2
  79. metadata +50 -4
@@ -3,9 +3,39 @@ require "spec_helper"
3
3
  describe Mongoid::Associations do
4
4
 
5
5
  before do
6
- Mongoid.database.collection(:people).drop
7
- Mongoid.database.collection(:games).drop
8
- Mongoid.database.collection(:posts).drop
6
+ Person.delete_all
7
+ Game.delete_all
8
+ Post.delete_all
9
+ end
10
+
11
+ context "criteria on has many embedded associations" do
12
+
13
+ before do
14
+ @person = Person.new(:title => "Sir")
15
+ @sf_apartment = Address.new(:street => "Genoa Pl", :state => "CA", :address_type => "Apartment")
16
+ @la_home = Address.new(:street => "Rodeo Dr", :state => "CA", :address_type => "Home")
17
+ @sf_home = Address.new(:street => "Pacific", :state => "CA", :address_type => "Home")
18
+ @person.addresses << [ @sf_apartment, @la_home, @sf_home ]
19
+ end
20
+
21
+ it "handles a single criteria" do
22
+ cas = @person.addresses.california
23
+ cas.size.should == 3
24
+ cas.should == [ @sf_apartment, @la_home, @sf_home ]
25
+ end
26
+
27
+ it "handles chained criteria" do
28
+ ca_homes = @person.addresses.california.homes
29
+ ca_homes.size.should == 2
30
+ ca_homes.should == [ @la_home, @sf_home ]
31
+ end
32
+
33
+ it "handles chained criteria with named scopes" do
34
+ ca_homes = @person.addresses.california.homes.rodeo
35
+ ca_homes.size.should == 1
36
+ ca_homes.should == [ @la_home ]
37
+ end
38
+
9
39
  end
10
40
 
11
41
  context "one-to-one relational associations" do
@@ -43,8 +73,8 @@ describe Mongoid::Associations do
43
73
  end
44
74
 
45
75
  it "sets the association on save" do
46
- @from_db = Person.find(@person.id)
47
- @from_db.posts.should == [@post]
76
+ from_db = Person.find(@person.id)
77
+ from_db.posts.should == [@post]
48
78
  end
49
79
 
50
80
  context "when building" do
@@ -60,6 +90,20 @@ describe Mongoid::Associations do
60
90
 
61
91
  end
62
92
 
93
+ context "finding associated objects" do
94
+
95
+ before do
96
+ @extra_post = Post.create(:title => "Orphan")
97
+ end
98
+
99
+ it "returns only those objects scoped to the parent" do
100
+ from_db = Person.find(@person.id)
101
+ Post.all.size.should == 2
102
+ from_db.posts.all.size.should == 1
103
+ end
104
+
105
+ end
106
+
63
107
  end
64
108
 
65
109
  context "nested embedded associations" do
@@ -99,6 +143,24 @@ describe Mongoid::Associations do
99
143
 
100
144
  end
101
145
 
146
+ context "when a has-one to has-many" do
147
+
148
+ before do
149
+ @person = Person.new(:title => "Sir", :ssn => "1")
150
+ @name = Name.new(:first_name => "Syd")
151
+ @person.name = @name
152
+ @person.save
153
+ end
154
+
155
+ it "persists all the associations properly" do
156
+ from_db = Person.find(@person.id)
157
+ translation = Translation.new(:language => "fr")
158
+ from_db.name.translations << translation
159
+ from_db.attributes[:name][:translations].should_not be_nil
160
+ end
161
+
162
+ end
163
+
102
164
  context "when a has-many to has-many" do
103
165
 
104
166
  before do
@@ -0,0 +1,22 @@
1
+ require "spec_helper"
2
+
3
+ describe Mongoid::Attributes do
4
+
5
+ context "when persisting nil attributes" do
6
+
7
+ before do
8
+ @person = Person.create(:score => nil, :ssn => "555-66-7777")
9
+ end
10
+
11
+ after do
12
+ Person.delete_all
13
+ end
14
+
15
+ it "the field should not exist" do
16
+ from_db = Person.find(@person.id)
17
+ from_db.attributes.has_key?(:score).should be_false
18
+ end
19
+
20
+ end
21
+
22
+ end
@@ -10,6 +10,37 @@ describe Mongoid::Commands do
10
10
  @person.delete
11
11
  end
12
12
 
13
+ describe ".create" do
14
+
15
+ it "saves and returns the document" do
16
+ person = Person.create(:title => "Sensei")
17
+ person.should be_a_kind_of(Person)
18
+ person.should_not be_a_new_record
19
+ end
20
+
21
+ end
22
+
23
+ describe ".create!" do
24
+
25
+ context "inserting with a field that is not unique" do
26
+
27
+ context "when a unique index exists" do
28
+
29
+ after do
30
+ Person.delete_all
31
+ end
32
+
33
+ it "raises an error" do
34
+ Person.create!(:ssn => "555-55-9999")
35
+ lambda { Person.create!(:ssn => "555-55-9999") }.should raise_error
36
+ end
37
+
38
+ end
39
+
40
+ end
41
+
42
+ end
43
+
13
44
  describe "#delete" do
14
45
 
15
46
  before do
@@ -56,16 +87,34 @@ describe Mongoid::Commands do
56
87
 
57
88
  end
58
89
 
90
+ describe "save!" do
91
+
92
+ context "inserting with a field that is not unique" do
93
+
94
+ context "when a unique index exists" do
95
+
96
+ it "raises an error" do
97
+ Person.create!(:ssn => "555-55-9999")
98
+ person = Person.new(:ssn => "555-55-9999")
99
+ lambda { person.save!(:ssn => "555-55-9999") }.should raise_error
100
+ end
101
+
102
+ end
103
+
104
+ end
105
+
106
+ end
107
+
59
108
  describe "#update_attributes" do
60
109
 
61
110
  context "when validation passes" do
62
111
 
63
112
  it "returns true" do
64
- @person.update_attributes(:title => "Blah").should be_true
113
+ @person.update_attributes(:ssn => "555-55-1234").should be_true
65
114
  end
66
115
 
67
116
  it "saves the attributes" do
68
- @person.update_attributes(:title => "Blah")
117
+ @person.update_attributes(:ssn => "555-55-1235", :title => "Blah")
69
118
  @from_db = Person.find(@person.id)
70
119
  @from_db.title.should == "Blah"
71
120
  end
@@ -74,16 +123,6 @@ describe Mongoid::Commands do
74
123
 
75
124
  end
76
125
 
77
- describe ".create" do
78
-
79
- it "saves and returns the document" do
80
- person = Person.create(:title => "Sensei")
81
- person.should be_a_kind_of(Person)
82
- person.should_not be_a_new_record
83
- end
84
-
85
- end
86
-
87
126
  describe ".delete_all" do
88
127
 
89
128
  it "returns true" do
@@ -6,7 +6,7 @@ describe Mongoid::Criteria do
6
6
 
7
7
  before do
8
8
  10.times do |n|
9
- Person.create(:title => "Sir", :age => (n * 10), :aliases => ["D", "Durran"])
9
+ Person.create(:title => "Sir", :age => (n * 10), :aliases => ["D", "Durran"], :ssn => "#{n}")
10
10
  end
11
11
  end
12
12
 
@@ -24,7 +24,7 @@ describe Mongoid::Criteria do
24
24
 
25
25
  before do
26
26
  10.times do |n|
27
- Person.create(:title => "Sir", :age => ((n + 1) * 10), :aliases => ["D", "Durran"])
27
+ Person.create(:title => "Sir", :age => ((n + 1) * 10), :aliases => ["D", "Durran"], :ssn => "#{n}")
28
28
  end
29
29
  end
30
30
 
@@ -42,7 +42,7 @@ describe Mongoid::Criteria do
42
42
 
43
43
  before do
44
44
  10.times do |n|
45
- Person.create(:title => "Sir", :age => 5, :aliases => ["D", "Durran"])
45
+ Person.create(:title => "Sir", :age => 5, :aliases => ["D", "Durran"], :ssn => "#{n}")
46
46
  end
47
47
  end
48
48
 
@@ -3,7 +3,7 @@ require "spec_helper"
3
3
  describe Mongoid::Document do
4
4
 
5
5
  before do
6
- Mongoid.database.collection(:people).drop
6
+ Person.delete_all
7
7
  end
8
8
 
9
9
  context "when document contains a hash field" do
@@ -50,7 +50,7 @@ describe Mongoid::Document do
50
50
 
51
51
  before do
52
52
  5.times do |n|
53
- Person.create(:title => "Sir")
53
+ Person.create(:title => "Sir", :ssn => "#{n}")
54
54
  end
55
55
  end
56
56
 
@@ -87,10 +87,10 @@ describe Mongoid::Document do
87
87
  context "chaining criteria scopes" do
88
88
 
89
89
  before do
90
- @one = Person.create(:title => "Mr", :age => 55, :terms => true)
91
- @two = Person.create(:title => "Sir", :age => 55, :terms => true)
92
- @three = Person.create(:title => "Sir", :age => 35, :terms => true)
93
- @four = Person.create(:title => "Sir", :age => 55, :terms => false)
90
+ @one = Person.create(:title => "Mr", :age => 55, :terms => true, :ssn => "q")
91
+ @two = Person.create(:title => "Sir", :age => 55, :terms => true, :ssn => "w")
92
+ @three = Person.create(:title => "Sir", :age => 35, :terms => true, :ssn => "e")
93
+ @four = Person.create(:title => "Sir", :age => 55, :terms => false, :ssn => "r")
94
94
  end
95
95
 
96
96
  it "finds by the merged criteria" do
@@ -120,7 +120,7 @@ describe Mongoid::Document do
120
120
 
121
121
  before do
122
122
  @person = Person.create(:title => "Lead")
123
- @person.addresses.create(:street => "1st Street")
123
+ address = @person.addresses.create(:street => "1st Street")
124
124
  @person.create_name(:first_name => "Emmanuel")
125
125
  @person.save
126
126
  end
@@ -288,7 +288,7 @@ describe Mongoid::Document do
288
288
 
289
289
  before do
290
290
  10.times do |num|
291
- Person.create(:title => "Test-#{num}")
291
+ Person.create(:title => "Test-#{num}", :ssn => "55#{num}")
292
292
  end
293
293
  end
294
294
 
@@ -5,7 +5,7 @@ describe Mongoid::Finders do
5
5
  describe "#find" do
6
6
 
7
7
  before do
8
- @document = Person.create(:title => "Mrs.")
8
+ @document = Person.create(:title => "Mrs.", :ssn => "another")
9
9
  end
10
10
 
11
11
  after do
@@ -2,6 +2,12 @@ require "spec_helper"
2
2
 
3
3
  describe Mongoid::Document do
4
4
 
5
+ before do
6
+ Browser.delete_all
7
+ Firefox.delete_all
8
+ Canvas.delete_all
9
+ end
10
+
5
11
  context "when document is a subclass of a root class" do
6
12
 
7
13
  before do
@@ -4,7 +4,7 @@ describe Mongoid::NamedScope do
4
4
 
5
5
  describe ".named_scope" do
6
6
 
7
- class Person
7
+ class ::Person
8
8
  named_scope :doctors, {:where => {:title => 'Dr.'} }
9
9
  named_scope :old, criteria.where(:age.gt => 50)
10
10
  end
@@ -38,6 +38,14 @@ class Person
38
38
  field :map, :type => Hash
39
39
  field :score, :type => Integer
40
40
  field :blood_alcohol_content, :type => Float
41
+ field :ssn
42
+
43
+ index :age
44
+ index :addresses
45
+ index :dob
46
+ index :name
47
+ index :title
48
+ index :ssn, :unique => true
41
49
 
42
50
  attr_reader :rescored
43
51
 
@@ -50,12 +58,6 @@ class Person
50
58
  accepts_nested_attributes_for :addresses, :reject_if => lambda { |attrs| attrs["street"].blank? }
51
59
  accepts_nested_attributes_for :name
52
60
 
53
- index :age
54
- index :addresses
55
- index :dob
56
- index :name
57
- index :title
58
-
59
61
  has_one_related :game
60
62
  has_many_related :posts
61
63
 
@@ -145,18 +147,34 @@ end
145
147
 
146
148
  class Address
147
149
  include Mongoid::Document
150
+ field :address_type
151
+ field :number, :type => Integer
148
152
  field :street
149
153
  field :city
150
154
  field :state
151
155
  field :post_code
152
156
  field :parent_title
157
+ field :services, :type => Array
153
158
  key :street
154
159
  has_many :locations
155
160
  belongs_to :addressable, :inverse_of => :addresses
156
161
 
162
+ named_scope :rodeo, where(:street => "Rodeo Dr")
163
+
157
164
  def set_parent=(set = false)
158
165
  self.parent_title = addressable.title if set
159
166
  end
167
+
168
+ class << self
169
+ def california
170
+ where(:state => "CA")
171
+ end
172
+
173
+ def homes
174
+ where(:address_type => "Home")
175
+ end
176
+
177
+ end
160
178
  end
161
179
 
162
180
  class Location
@@ -171,6 +189,7 @@ class Name
171
189
  field :last_name
172
190
  field :parent_title
173
191
  key :first_name, :last_name
192
+ has_many :translations
174
193
  belongs_to :person, :inverse_of => :name
175
194
 
176
195
  def set_parent=(set = false)
@@ -178,6 +197,12 @@ class Name
178
197
  end
179
198
  end
180
199
 
200
+ class Translation
201
+ include Mongoid::Document
202
+ field :language
203
+ belongs_to :name, :inverse_of => :translations
204
+ end
205
+
181
206
  class Comment
182
207
  include Mongoid::Document
183
208
  include Mongoid::Versioning
@@ -292,3 +317,19 @@ module Medical
292
317
  field :name
293
318
  end
294
319
  end
320
+
321
+ ###################################
322
+
323
+ class Author
324
+ include Mongoid::Document
325
+ field :name
326
+ has_many :books
327
+ end
328
+
329
+ class Book
330
+ include Mongoid::Document
331
+ field :title
332
+ belongs_to :author, :inverse_of => :books
333
+ end
334
+
335
+
@@ -193,6 +193,48 @@ describe Mongoid::Associations::HasManyRelated do
193
193
 
194
194
  end
195
195
 
196
+ context "when finding all with conditions" do
197
+
198
+ before do
199
+ @post = stub
200
+ end
201
+
202
+ it "passes the conditions to the association class" do
203
+ Post.expects(:find).with(:all, :conditions => { :title => "Testing", :person_id => @parent.id }).returns([@post])
204
+ posts = @association.find(:all, :conditions => { :title => "Testing" })
205
+ posts.should == [@post]
206
+ end
207
+
208
+ end
209
+
210
+ context "when finding first with conditions" do
211
+
212
+ before do
213
+ @post = stub
214
+ end
215
+
216
+ it "passes the conditions to the association class" do
217
+ Post.expects(:find).with(:first, :conditions => { :title => "Testing", :person_id => @parent.id }).returns(@post)
218
+ post = @association.find(:first, :conditions => { :title => "Testing" })
219
+ post.should == @post
220
+ end
221
+
222
+ end
223
+
224
+ context "when finding last with conditions" do
225
+
226
+ before do
227
+ @post = stub
228
+ end
229
+
230
+ it "passes the conditions to the association class" do
231
+ Post.expects(:find).with(:last, :conditions => { :title => "Testing", :person_id => @parent.id }).returns(@post)
232
+ post = @association.find(:last, :conditions => { :title => "Testing" })
233
+ post.should == @post
234
+ end
235
+
236
+ end
237
+
196
238
  end
197
239
 
198
240
  describe ".initialize" do