djsun-mongo_mapper 0.5.6.6 → 0.5.8.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/.gitignore +3 -1
- data/Rakefile +13 -8
- data/VERSION +1 -1
- data/djsun-mongo_mapper.gemspec +17 -21
- data/lib/mongo_mapper/associations/base.rb +32 -36
- data/lib/mongo_mapper/associations/many_documents_as_proxy.rb +0 -2
- data/lib/mongo_mapper/associations/many_documents_proxy.rb +19 -10
- data/lib/mongo_mapper/associations/many_embedded_polymorphic_proxy.rb +2 -2
- data/lib/mongo_mapper/associations/many_embedded_proxy.rb +21 -36
- data/lib/mongo_mapper/associations/many_polymorphic_proxy.rb +1 -1
- data/lib/mongo_mapper/associations/proxy.rb +3 -2
- data/lib/mongo_mapper/associations.rb +114 -8
- data/lib/mongo_mapper/callbacks.rb +18 -0
- data/lib/mongo_mapper/document.rb +173 -37
- data/lib/mongo_mapper/dynamic_finder.rb +1 -1
- data/lib/mongo_mapper/embedded_document.rb +9 -13
- data/lib/mongo_mapper/finder_options.rb +67 -44
- data/lib/mongo_mapper/pagination.rb +2 -0
- data/lib/mongo_mapper/serialization.rb +1 -1
- data/lib/mongo_mapper/serializers/json_serializer.rb +1 -1
- data/lib/mongo_mapper/support.rb +9 -0
- data/lib/mongo_mapper/validations.rb +12 -42
- data/lib/mongo_mapper.rb +11 -5
- data/test/functional/associations/test_belongs_to_polymorphic_proxy.rb +5 -5
- data/test/functional/associations/test_belongs_to_proxy.rb +29 -31
- data/test/functional/associations/test_many_documents_as_proxy.rb +5 -5
- data/test/functional/associations/test_many_embedded_polymorphic_proxy.rb +27 -3
- data/test/functional/associations/test_many_embedded_proxy.rb +58 -38
- data/test/functional/associations/test_many_polymorphic_proxy.rb +45 -3
- data/test/functional/associations/test_many_proxy.rb +61 -11
- data/test/functional/test_associations.rb +3 -3
- data/test/functional/test_binary.rb +1 -1
- data/test/functional/test_callbacks.rb +1 -1
- data/test/functional/test_dirty.rb +3 -3
- data/test/functional/test_document.rb +62 -58
- data/test/functional/test_embedded_document.rb +1 -1
- data/test/functional/test_pagination.rb +1 -1
- data/test/functional/test_rails_compatibility.rb +1 -1
- data/test/functional/test_validations.rb +46 -14
- data/test/models.rb +87 -35
- data/test/support/{test_timing.rb → timing.rb} +1 -1
- data/test/test_helper.rb +8 -13
- data/test/unit/serializers/test_json_serializer.rb +0 -4
- data/test/unit/test_association_base.rb +24 -8
- data/test/unit/test_document.rb +40 -71
- data/test/unit/test_embedded_document.rb +27 -67
- data/test/unit/test_finder_options.rb +16 -0
- data/test/unit/test_key.rb +5 -17
- data/test/unit/test_mongomapper.rb +2 -2
- data/test/unit/test_pagination.rb +4 -0
- metadata +10 -12
- data/mongo_mapper.gemspec +0 -170
- data/test/functional/associations/test_namespace.rb +0 -27
@@ -4,67 +4,37 @@ module MongoMapper
|
|
4
4
|
def validates_uniqueness_of(*args)
|
5
5
|
add_validations(args, MongoMapper::Validations::ValidatesUniquenessOf)
|
6
6
|
end
|
7
|
-
|
8
|
-
def validates_exclusion_of(*args)
|
9
|
-
add_validations(args, MongoMapper::Validations::ValidatesExclusionOf)
|
10
|
-
end
|
11
|
-
|
12
|
-
def validates_inclusion_of(*args)
|
13
|
-
add_validations(args, MongoMapper::Validations::ValidatesInclusionOf)
|
14
|
-
end
|
15
7
|
end
|
16
8
|
|
17
9
|
class ValidatesUniquenessOf < Validatable::ValidationBase
|
18
|
-
option :scope
|
19
|
-
|
10
|
+
option :scope, :case_sensitive
|
11
|
+
default :case_sensitive => true
|
12
|
+
|
20
13
|
def valid?(instance)
|
21
14
|
value = instance[attribute]
|
22
15
|
return true if allow_blank && value.blank?
|
23
|
-
|
16
|
+
base_conditions = case_sensitive ? {self.attribute => value} : {}
|
17
|
+
doc = instance.class.first(base_conditions.merge(scope_conditions(instance)).merge(where_conditions(instance)))
|
24
18
|
doc.nil? || instance.id == doc.id
|
25
19
|
end
|
26
20
|
|
27
21
|
def message(instance)
|
28
22
|
super || "has already been taken"
|
29
23
|
end
|
30
|
-
|
24
|
+
|
31
25
|
def scope_conditions(instance)
|
32
26
|
return {} unless scope
|
33
27
|
Array(scope).inject({}) do |conditions, key|
|
34
28
|
conditions.merge(key => instance[key])
|
35
29
|
end
|
36
30
|
end
|
37
|
-
end
|
38
|
-
|
39
|
-
class ValidatesExclusionOf < Validatable::ValidationBase
|
40
|
-
required_option :within
|
41
|
-
|
42
|
-
def valid?(instance)
|
43
|
-
value = instance[attribute]
|
44
|
-
return true if allow_nil && value.nil?
|
45
|
-
return true if allow_blank && value.blank?
|
46
|
-
|
47
|
-
!within.include?(instance[attribute])
|
48
|
-
end
|
49
|
-
|
50
|
-
def message(instance)
|
51
|
-
super || "is reserved"
|
52
|
-
end
|
53
|
-
end
|
54
31
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
return true if allow_blank && value.blank?
|
62
|
-
|
63
|
-
within.include?(value)
|
64
|
-
end
|
65
|
-
|
66
|
-
def message(instance)
|
67
|
-
super || "is not in the list"
|
32
|
+
def where_conditions(instance)
|
33
|
+
conditions = {}
|
34
|
+
unless case_sensitive
|
35
|
+
conditions.merge!({'$where' => "this.#{attribute}.toLowerCase() == '#{instance[attribute].downcase}'"})
|
36
|
+
end
|
37
|
+
conditions
|
68
38
|
end
|
69
39
|
end
|
70
40
|
end
|
data/lib/mongo_mapper.rb
CHANGED
@@ -1,13 +1,19 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
gem 'activesupport', '>= 2.3'
|
3
1
|
require 'active_support'
|
4
2
|
require 'mongo'
|
5
3
|
require 'validatable'
|
6
4
|
|
7
5
|
module MongoMapper
|
8
|
-
|
9
|
-
|
10
|
-
|
6
|
+
# generic MM error
|
7
|
+
class MongoMapperError < StandardError; end
|
8
|
+
|
9
|
+
# raised when key expected to exist but not found
|
10
|
+
class KeyNotFound < MongoMapperError; end
|
11
|
+
|
12
|
+
# raised when document expected but not found
|
13
|
+
class DocumentNotFound < MongoMapperError; end
|
14
|
+
|
15
|
+
# raised when document not valid and using !
|
16
|
+
class DocumentNotValid < MongoMapperError
|
11
17
|
def initialize(document)
|
12
18
|
@document = document
|
13
19
|
super("Validation failed: #{@document.errors.full_messages.join(", ")}")
|
@@ -3,8 +3,8 @@ require 'models'
|
|
3
3
|
|
4
4
|
class BelongsToPolymorphicProxyTest < Test::Unit::TestCase
|
5
5
|
def setup
|
6
|
-
Status.collection.
|
7
|
-
Project.collection.
|
6
|
+
Status.collection.remove
|
7
|
+
Project.collection.remove
|
8
8
|
end
|
9
9
|
|
10
10
|
should "default to nil" do
|
@@ -14,7 +14,7 @@ class BelongsToPolymorphicProxyTest < Test::Unit::TestCase
|
|
14
14
|
end
|
15
15
|
|
16
16
|
should "be able to replace the association" do
|
17
|
-
status = Status.new
|
17
|
+
status = Status.new(:name => 'Foo!')
|
18
18
|
project = Project.new(:name => "mongomapper")
|
19
19
|
status.target = project
|
20
20
|
status.save.should be_true
|
@@ -27,7 +27,7 @@ class BelongsToPolymorphicProxyTest < Test::Unit::TestCase
|
|
27
27
|
end
|
28
28
|
|
29
29
|
should "unset the association" do
|
30
|
-
status = Status.new
|
30
|
+
status = Status.new(:name => 'Foo!')
|
31
31
|
project = Project.new(:name => "mongomapper")
|
32
32
|
status.target = project
|
33
33
|
status.save.should be_true
|
@@ -41,7 +41,7 @@ class BelongsToPolymorphicProxyTest < Test::Unit::TestCase
|
|
41
41
|
|
42
42
|
context "association id set but document not found" do
|
43
43
|
setup do
|
44
|
-
@status = Status.new
|
44
|
+
@status = Status.new(:name => 'Foo!')
|
45
45
|
project = Project.new(:name => "mongomapper")
|
46
46
|
@status.target = project
|
47
47
|
@status.save.should be_true
|
@@ -2,48 +2,46 @@ require 'test_helper'
|
|
2
2
|
require 'models'
|
3
3
|
|
4
4
|
class BelongsToProxyTest < Test::Unit::TestCase
|
5
|
-
def setup
|
6
|
-
|
7
|
-
|
5
|
+
def setup
|
6
|
+
@post_class = Class.new do
|
7
|
+
include MongoMapper::Document
|
8
|
+
end
|
9
|
+
|
10
|
+
@comment_class = Class.new do
|
11
|
+
include MongoMapper::Document
|
12
|
+
key :post_id, String
|
13
|
+
end
|
14
|
+
@comment_class.belongs_to :post, :class => @post_class
|
15
|
+
|
16
|
+
@post_class.collection.remove
|
17
|
+
@comment_class.collection.remove
|
8
18
|
end
|
9
19
|
|
10
20
|
should "default to nil" do
|
11
|
-
|
12
|
-
status.project.nil?.should == true
|
13
|
-
status.project.inspect.should == 'nil'
|
21
|
+
@comment_class.new.post.nil?.should be_true
|
14
22
|
end
|
15
23
|
|
16
24
|
should "be able to replace the association" do
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
status.save.should be_true
|
25
|
+
post = @post_class.new(:name => 'mongomapper')
|
26
|
+
comment = @comment_class.new(:name => 'Foo!', :post => post)
|
27
|
+
comment.save.should be_true
|
21
28
|
|
22
|
-
|
23
|
-
|
24
|
-
|
29
|
+
comment = comment.reload
|
30
|
+
comment.post.should == post
|
31
|
+
comment.post.nil?.should be_false
|
25
32
|
end
|
26
33
|
|
27
34
|
should "unset the association" do
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
status.save.should be_true
|
35
|
+
post = @post_class.new(:name => 'mongomapper')
|
36
|
+
comment = @comment_class.new(:name => 'Foo!', :post => post)
|
37
|
+
comment.save.should be_true
|
32
38
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
from_db.project.inspect.should == 'nil'
|
39
|
+
comment = comment.reload
|
40
|
+
comment.post = nil
|
41
|
+
comment.post.nil?.should be_true
|
37
42
|
end
|
38
43
|
|
39
|
-
|
40
|
-
|
41
|
-
@status = Status.new(:name => 'Foo', :project_id => '1234')
|
42
|
-
end
|
43
|
-
|
44
|
-
should "return nil instead of raising error" do
|
45
|
-
@status.project.nil?.should be_true
|
46
|
-
@status.project.inspect.should == 'nil'
|
47
|
-
end
|
44
|
+
should "return nil if id set but document not found" do
|
45
|
+
@comment_class.new(:name => 'Foo', :post_id => '1234').post.nil?.should be_true
|
48
46
|
end
|
49
|
-
end
|
47
|
+
end
|
@@ -3,8 +3,8 @@ require 'models'
|
|
3
3
|
|
4
4
|
class ManyDocumentsAsProxyTest < Test::Unit::TestCase
|
5
5
|
def setup
|
6
|
-
Post.collection.
|
7
|
-
PostComment.collection.
|
6
|
+
Post.collection.remove
|
7
|
+
PostComment.collection.remove
|
8
8
|
end
|
9
9
|
|
10
10
|
should "default reader to empty array" do
|
@@ -171,20 +171,20 @@ class ManyDocumentsAsProxyTest < Test::Unit::TestCase
|
|
171
171
|
|
172
172
|
should "not work for id not in association" do
|
173
173
|
lambda {
|
174
|
-
@post.comments.find(@comment5.id)
|
174
|
+
@post.comments.find!(@comment5.id)
|
175
175
|
}.should raise_error(MongoMapper::DocumentNotFound)
|
176
176
|
end
|
177
177
|
end
|
178
178
|
|
179
179
|
context "with multiple ids" do
|
180
180
|
should "work for ids in association" do
|
181
|
-
posts = @post.comments.find(@comment1.id, @comment2.id)
|
181
|
+
posts = @post.comments.find!(@comment1.id, @comment2.id)
|
182
182
|
posts.should == [@comment1, @comment2]
|
183
183
|
end
|
184
184
|
|
185
185
|
should "not work for ids not in association" do
|
186
186
|
lambda {
|
187
|
-
@post.comments.find(@comment1.id, @comment2.id, @comment4.id)
|
187
|
+
@post.comments.find!(@comment1.id, @comment2.id, @comment4.id)
|
188
188
|
}.should raise_error(MongoMapper::DocumentNotFound)
|
189
189
|
end
|
190
190
|
end
|
@@ -3,8 +3,8 @@ require 'models'
|
|
3
3
|
|
4
4
|
class ManyEmbeddedPolymorphicProxyTest < Test::Unit::TestCase
|
5
5
|
def setup
|
6
|
-
Catalog.collection.
|
7
|
-
TrModels::Fleet.collection.
|
6
|
+
Catalog.collection.remove
|
7
|
+
TrModels::Fleet.collection.remove
|
8
8
|
end
|
9
9
|
|
10
10
|
should "default reader to empty array" do
|
@@ -129,4 +129,28 @@ class ManyEmbeddedPolymorphicProxyTest < Test::Unit::TestCase
|
|
129
129
|
from_db.transports[2].icu.should == true
|
130
130
|
end
|
131
131
|
end
|
132
|
-
|
132
|
+
|
133
|
+
context "extending the association" do
|
134
|
+
should "work using a block passed to many" do
|
135
|
+
catalog = Catalog.new
|
136
|
+
medias = catalog.medias = [
|
137
|
+
Video.new("file" => "video.mpg", "length" => 3600, :visible => true),
|
138
|
+
Music.new("file" => "music.mp3", "bitrate" => "128kbps", :visible => true),
|
139
|
+
Image.new("file" => "image.png", "width" => 800, "height" => 600, :visible => false)
|
140
|
+
]
|
141
|
+
catalog.save
|
142
|
+
catalog.medias.visible.should == [medias[0], medias[1]]
|
143
|
+
end
|
144
|
+
|
145
|
+
should "work using many's :extend option" do
|
146
|
+
fleet = TrModels::Fleet.new
|
147
|
+
transports = fleet.transports = [
|
148
|
+
TrModels::Car.new("license_plate" => "ABC1223", "model" => "Honda Civic", "year" => 2003, :purchased_on => 2.years.ago.to_date),
|
149
|
+
TrModels::Bus.new("license_plate" => "XYZ9090", "max_passengers" => 51, :purchased_on => 3.years.ago.to_date),
|
150
|
+
TrModels::Ambulance.new("license_plate" => "HDD3030", "icu" => true, :purchased_on => 1.year.ago.to_date)
|
151
|
+
]
|
152
|
+
fleet.save
|
153
|
+
fleet.transports.to_be_replaced.should == [transports[1]]
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
@@ -3,8 +3,8 @@ require 'models'
|
|
3
3
|
|
4
4
|
class ManyEmbeddedProxyTest < Test::Unit::TestCase
|
5
5
|
def setup
|
6
|
-
Project.collection.
|
7
|
-
RealPerson.collection.
|
6
|
+
Project.collection.remove
|
7
|
+
RealPerson.collection.remove
|
8
8
|
end
|
9
9
|
|
10
10
|
should "default reader to empty array" do
|
@@ -17,13 +17,6 @@ class ManyEmbeddedProxyTest < Test::Unit::TestCase
|
|
17
17
|
project.addresses.push Address.new
|
18
18
|
project.addresses.size.should == 2
|
19
19
|
end
|
20
|
-
|
21
|
-
should "allow finding :all embedded documents" do
|
22
|
-
project = Project.new
|
23
|
-
project.addresses << Address.new
|
24
|
-
project.addresses << Address.new
|
25
|
-
project.save
|
26
|
-
end
|
27
20
|
|
28
21
|
should "be embedded in document on save" do
|
29
22
|
sb = Address.new(:city => 'South Bend', :state => 'IN')
|
@@ -45,7 +38,7 @@ class ManyEmbeddedProxyTest < Test::Unit::TestCase
|
|
45
38
|
set_collection_name 'test'
|
46
39
|
key :person, Person
|
47
40
|
end
|
48
|
-
@document.collection.
|
41
|
+
@document.collection.remove
|
49
42
|
|
50
43
|
meg = Person.new(:name => "Meg")
|
51
44
|
meg.child = Person.new(:name => "Steve")
|
@@ -92,7 +85,7 @@ class ManyEmbeddedProxyTest < Test::Unit::TestCase
|
|
92
85
|
set_collection_name 'test'
|
93
86
|
many :people
|
94
87
|
end
|
95
|
-
@document.collection.
|
88
|
+
@document.collection.remove
|
96
89
|
end
|
97
90
|
|
98
91
|
should "persist all embedded documents" do
|
@@ -130,45 +123,72 @@ class ManyEmbeddedProxyTest < Test::Unit::TestCase
|
|
130
123
|
doc.people.first.pets.first._root_document.should == doc
|
131
124
|
end
|
132
125
|
|
133
|
-
should "create properly-named reference to parent document when building off association proxy" do
|
134
|
-
person = RealPerson.new
|
135
|
-
pet = person.pets.build
|
136
|
-
person.should == pet.real_person
|
137
|
-
end
|
138
|
-
|
139
|
-
|
140
126
|
should "create a reference to the root document for all embedded documents" do
|
141
|
-
meg = Person.new(:name => "Meg")
|
142
127
|
sparky = Pet.new(:name => "Sparky", :species => "Dog")
|
143
|
-
|
128
|
+
meg = Person.new(:name => "Meg", :pets => [sparky])
|
144
129
|
doc = @document.new
|
145
|
-
|
146
|
-
meg.pets << sparky
|
147
|
-
|
148
130
|
doc.people << meg
|
149
131
|
doc.save
|
150
132
|
|
151
|
-
|
152
|
-
|
153
|
-
|
133
|
+
doc = doc.reload
|
134
|
+
doc.people.first._root_document.should == doc
|
135
|
+
doc.people.first.pets.first._root_document.should == doc
|
154
136
|
end
|
155
137
|
end
|
156
138
|
|
157
|
-
should "allow
|
158
|
-
meg = Person.new(:name => "Meg")
|
139
|
+
should "allow finding by id" do
|
159
140
|
sparky = Pet.new(:name => "Sparky", :species => "Dog")
|
160
|
-
|
161
|
-
meg.pets
|
162
|
-
|
163
|
-
meg.pets.find(:all).should include(sparky)
|
141
|
+
meg = Person.new(:name => "Meg", :pets => [sparky])
|
142
|
+
meg.pets.find(sparky.id).should == sparky
|
164
143
|
end
|
165
144
|
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
145
|
+
context "extending the association" do
|
146
|
+
setup do
|
147
|
+
@address_class = Class.new do
|
148
|
+
include MongoMapper::EmbeddedDocument
|
149
|
+
key :address, String
|
150
|
+
key :city, String
|
151
|
+
key :state, String
|
152
|
+
key :zip, Integer
|
153
|
+
end
|
154
|
+
|
155
|
+
@project_class = Class.new do
|
156
|
+
include MongoMapper::Document
|
157
|
+
key :name, String
|
158
|
+
end
|
159
|
+
|
160
|
+
@project_class.collection.remove
|
161
|
+
end
|
171
162
|
|
172
|
-
|
163
|
+
should "work using a block passed to many" do
|
164
|
+
@project_class.many :addresses, :class => @address_class do
|
165
|
+
def find_all_by_state(state)
|
166
|
+
find_all { |a| a.state == state }
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
addr1 = @address_class.new(:address => "Gate-3 Lankershim Blvd.", :city => "Universal City", :state => "CA", :zip => "91608")
|
171
|
+
addr2 = @address_class.new(:address => "3000 W. Alameda Ave.", :city => "Burbank", :state => "CA", :zip => "91523")
|
172
|
+
addr3 = @address_class.new(:address => "111 Some Ln", :city => "Nashville", :state => "TN", :zip => "37211")
|
173
|
+
project = @project_class.create(:name => "Some Project", :addresses => [addr1, addr2, addr3])
|
174
|
+
|
175
|
+
project.addresses.find_all_by_state("CA").should == [addr1, addr2]
|
176
|
+
end
|
177
|
+
|
178
|
+
should "work using many's :extend option" do
|
179
|
+
module FindByCity
|
180
|
+
def find_by_city(city)
|
181
|
+
find_all { |a| a.city == city }
|
182
|
+
end
|
183
|
+
end
|
184
|
+
@project_class.many :addresses, :class => @address_class, :extend => FindByCity
|
185
|
+
|
186
|
+
addr1 = @address_class.new(:address => "Gate-3 Lankershim Blvd.", :city => "Universal City", :state => "CA", :zip => "91608")
|
187
|
+
addr2 = @address_class.new(:address => "3000 W. Alameda Ave.", :city => "Burbank", :state => "CA", :zip => "91523")
|
188
|
+
addr3 = @address_class.new(:address => "111 Some Ln", :city => "Nashville", :state => "TN", :zip => "37211")
|
189
|
+
project = @project_class.create(:name => "Some Project", :addresses => [addr1, addr2, addr3])
|
190
|
+
|
191
|
+
project.addresses.find_by_city('Burbank').should == [addr2]
|
192
|
+
end
|
173
193
|
end
|
174
194
|
end
|
@@ -3,7 +3,8 @@ require 'models'
|
|
3
3
|
|
4
4
|
class ManyPolymorphicProxyTest < Test::Unit::TestCase
|
5
5
|
def setup
|
6
|
-
Room.collection.
|
6
|
+
Room.collection.remove
|
7
|
+
Message.collection.remove
|
7
8
|
end
|
8
9
|
|
9
10
|
should "default reader to empty array" do
|
@@ -258,11 +259,25 @@ class ManyPolymorphicProxyTest < Test::Unit::TestCase
|
|
258
259
|
|
259
260
|
should "not work for id not in association" do
|
260
261
|
lambda {
|
261
|
-
@lounge.messages.find(@hm2.id)
|
262
|
+
@lounge.messages.find!(@hm2.id)
|
262
263
|
}.should raise_error(MongoMapper::DocumentNotFound)
|
263
264
|
end
|
264
265
|
end
|
265
266
|
|
267
|
+
context "with query options/criteria" do
|
268
|
+
should "work with order on association" do
|
269
|
+
@lounge.messages.should == [@lm1, @lm2]
|
270
|
+
end
|
271
|
+
|
272
|
+
should "allow overriding the order provided to the association" do
|
273
|
+
@lounge.messages.all(:order => 'position desc').should == [@lm2, @lm1]
|
274
|
+
end
|
275
|
+
|
276
|
+
should "allow using conditions on association" do
|
277
|
+
@hall.latest_messages.should == [@hm3, @hm2]
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
266
281
|
context "with multiple ids" do
|
267
282
|
should "work for ids in association" do
|
268
283
|
messages = @lounge.messages.find(@lm1.id, @lm2.id)
|
@@ -271,7 +286,7 @@ class ManyPolymorphicProxyTest < Test::Unit::TestCase
|
|
271
286
|
|
272
287
|
should "not work for ids not in association" do
|
273
288
|
lambda {
|
274
|
-
@lounge.messages.find(@lm1.id, @lm2.id, @hm2.id)
|
289
|
+
@lounge.messages.find!(@lm1.id, @lm2.id, @hm2.id)
|
275
290
|
}.should raise_error(MongoMapper::DocumentNotFound)
|
276
291
|
end
|
277
292
|
end
|
@@ -294,4 +309,31 @@ class ManyPolymorphicProxyTest < Test::Unit::TestCase
|
|
294
309
|
end
|
295
310
|
end
|
296
311
|
end
|
312
|
+
|
313
|
+
context "extending the association" do
|
314
|
+
should "work using a block passed to many" do
|
315
|
+
room = Room.new(:name => "Amazing Room")
|
316
|
+
messages = room.messages = [
|
317
|
+
Enter.new(:body => 'John entered room', :position => 3),
|
318
|
+
Chat.new(:body => 'Heyyyoooo!', :position => 4),
|
319
|
+
Exit.new(:body => 'John exited room', :position => 5),
|
320
|
+
Enter.new(:body => 'Steve entered room', :position => 6),
|
321
|
+
Chat.new(:body => 'Anyone there?', :position => 7),
|
322
|
+
Exit.new(:body => 'Steve exited room', :position => 8)
|
323
|
+
]
|
324
|
+
room.save
|
325
|
+
room.messages.older.should == messages[3..5]
|
326
|
+
end
|
327
|
+
|
328
|
+
should "work using many's :extend option" do
|
329
|
+
room = Room.new(:name => "Amazing Room")
|
330
|
+
accounts = room.accounts = [
|
331
|
+
Bot.new(:last_logged_in => 3.weeks.ago),
|
332
|
+
User.new(:last_logged_in => nil),
|
333
|
+
Bot.new(:last_logged_in => 1.week.ago)
|
334
|
+
]
|
335
|
+
room.save
|
336
|
+
room.accounts.inactive.should == [accounts[1]]
|
337
|
+
end
|
338
|
+
end
|
297
339
|
end
|
@@ -3,8 +3,8 @@ require 'models'
|
|
3
3
|
|
4
4
|
class ManyProxyTest < Test::Unit::TestCase
|
5
5
|
def setup
|
6
|
-
Project.collection.
|
7
|
-
Status.collection.
|
6
|
+
Project.collection.remove
|
7
|
+
Status.collection.remove
|
8
8
|
end
|
9
9
|
|
10
10
|
should "default reader to empty array" do
|
@@ -14,9 +14,9 @@ class ManyProxyTest < Test::Unit::TestCase
|
|
14
14
|
|
15
15
|
should "allow adding to association like it was an array" do
|
16
16
|
project = Project.new
|
17
|
-
project.statuses << Status.new
|
18
|
-
project.statuses.push Status.new
|
19
|
-
project.statuses.concat Status.new
|
17
|
+
project.statuses << Status.new(:name => 'Foo1!')
|
18
|
+
project.statuses.push Status.new(:name => 'Foo2!')
|
19
|
+
project.statuses.concat Status.new(:name => 'Foo3!')
|
20
20
|
project.statuses.size.should == 3
|
21
21
|
end
|
22
22
|
|
@@ -59,14 +59,14 @@ class ManyProxyTest < Test::Unit::TestCase
|
|
59
59
|
context "create" do
|
60
60
|
should "assign foreign key" do
|
61
61
|
project = Project.create
|
62
|
-
status = project.statuses.create
|
62
|
+
status = project.statuses.create(:name => 'Foo!')
|
63
63
|
status.project_id.should == project.id
|
64
64
|
end
|
65
65
|
|
66
66
|
should "save record" do
|
67
67
|
project = Project.create
|
68
68
|
lambda {
|
69
|
-
project.statuses.create
|
69
|
+
project.statuses.create(:name => 'Foo!')
|
70
70
|
}.should change { Status.count }
|
71
71
|
end
|
72
72
|
|
@@ -77,13 +77,42 @@ class ManyProxyTest < Test::Unit::TestCase
|
|
77
77
|
end
|
78
78
|
end
|
79
79
|
|
80
|
+
context "create!" do
|
81
|
+
should "assign foreign key" do
|
82
|
+
project = Project.create
|
83
|
+
status = project.statuses.create!(:name => 'Foo!')
|
84
|
+
status.project_id.should == project.id
|
85
|
+
end
|
86
|
+
|
87
|
+
should "save record" do
|
88
|
+
project = Project.create
|
89
|
+
lambda {
|
90
|
+
project.statuses.create!(:name => 'Foo!')
|
91
|
+
}.should change { Status.count }
|
92
|
+
end
|
93
|
+
|
94
|
+
should "allow passing attributes" do
|
95
|
+
project = Project.create
|
96
|
+
status = project.statuses.create!(:name => 'Foo!')
|
97
|
+
status.name.should == 'Foo!'
|
98
|
+
end
|
99
|
+
|
100
|
+
should "raise exception if not valid" do
|
101
|
+
project = Project.create
|
102
|
+
lambda {
|
103
|
+
project.statuses.create!(:name => nil)
|
104
|
+
}.should raise_error(MongoMapper::DocumentNotValid)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
|
80
109
|
context "count" do
|
81
110
|
should "work scoped to association" do
|
82
111
|
project = Project.create
|
83
|
-
3.times { project.statuses.create }
|
112
|
+
3.times { project.statuses.create(:name => 'Foo!') }
|
84
113
|
|
85
114
|
other_project = Project.create
|
86
|
-
2.times { other_project.statuses.create }
|
115
|
+
2.times { other_project.statuses.create(:name => 'Foo!') }
|
87
116
|
|
88
117
|
project.statuses.count.should == 3
|
89
118
|
other_project.statuses.count.should == 2
|
@@ -292,7 +321,7 @@ class ManyProxyTest < Test::Unit::TestCase
|
|
292
321
|
|
293
322
|
should "not work for id not in association" do
|
294
323
|
lambda {
|
295
|
-
@project1.statuses.find(@archived.id)
|
324
|
+
@project1.statuses.find!(@archived.id)
|
296
325
|
}.should raise_error(MongoMapper::DocumentNotFound)
|
297
326
|
end
|
298
327
|
end
|
@@ -305,7 +334,7 @@ class ManyProxyTest < Test::Unit::TestCase
|
|
305
334
|
|
306
335
|
should "not work for ids not in association" do
|
307
336
|
lambda {
|
308
|
-
@project1.statuses.find(@brand_new.id, @complete.id, @archived.id)
|
337
|
+
@project1.statuses.find!(@brand_new.id, @complete.id, @archived.id)
|
309
338
|
}.should raise_error(MongoMapper::DocumentNotFound)
|
310
339
|
end
|
311
340
|
end
|
@@ -328,4 +357,25 @@ class ManyProxyTest < Test::Unit::TestCase
|
|
328
357
|
end
|
329
358
|
end
|
330
359
|
end
|
360
|
+
|
361
|
+
context "extending the association" do
|
362
|
+
should "work using a block passed to many" do
|
363
|
+
project = Project.new(:name => "Some Project")
|
364
|
+
status1 = Status.new(:name => "New")
|
365
|
+
status2 = Status.new(:name => "Assigned")
|
366
|
+
status3 = Status.new(:name => "Closed")
|
367
|
+
project.statuses = [status1, status2, status3]
|
368
|
+
project.save
|
369
|
+
project.statuses.open.should == [status1, status2]
|
370
|
+
end
|
371
|
+
|
372
|
+
should "work using many's :extend option" do
|
373
|
+
project = Project.new(:name => "Some Project")
|
374
|
+
collaborator1 = Collaborator.new(:name => "zing")
|
375
|
+
collaborator2 = Collaborator.new(:name => "zang")
|
376
|
+
project.collaborators = [collaborator1, collaborator2]
|
377
|
+
project.save
|
378
|
+
project.collaborators.top.should == collaborator1
|
379
|
+
end
|
380
|
+
end
|
331
381
|
end
|
@@ -8,7 +8,7 @@ class AssociationsTest < Test::Unit::TestCase
|
|
8
8
|
|
9
9
|
many :posts, :class_name => 'AssociationsTest::AwesomePost', :foreign_key => :creator_id
|
10
10
|
end
|
11
|
-
AwesomeUser.collection.
|
11
|
+
AwesomeUser.collection.remove
|
12
12
|
|
13
13
|
class AwesomeTag
|
14
14
|
include MongoMapper::EmbeddedDocument
|
@@ -28,8 +28,8 @@ class AssociationsTest < Test::Unit::TestCase
|
|
28
28
|
many :tags, :class_name => 'AssociationsTest::AwesomeTag', :foreign_key => :post_id
|
29
29
|
end
|
30
30
|
|
31
|
-
AwesomeUser.collection.
|
32
|
-
AwesomePost.collection.
|
31
|
+
AwesomeUser.collection.remove
|
32
|
+
AwesomePost.collection.remove
|
33
33
|
|
34
34
|
user = AwesomeUser.create
|
35
35
|
tag1 = AwesomeTag.new(:name => 'awesome')
|