djsun-mongomapper 0.3.5.5 → 0.4.1.2

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.
Files changed (44) hide show
  1. data/README.rdoc +38 -38
  2. data/Rakefile +87 -73
  3. data/VERSION +1 -1
  4. data/lib/mongomapper.rb +67 -71
  5. data/lib/mongomapper/associations.rb +86 -84
  6. data/lib/mongomapper/associations/belongs_to_polymorphic_proxy.rb +34 -34
  7. data/lib/mongomapper/associations/many_embedded_proxy.rb +67 -17
  8. data/lib/mongomapper/associations/proxy.rb +74 -73
  9. data/lib/mongomapper/document.rb +342 -348
  10. data/lib/mongomapper/embedded_document.rb +354 -274
  11. data/lib/mongomapper/finder_options.rb +84 -84
  12. data/lib/mongomapper/key.rb +32 -76
  13. data/lib/mongomapper/rails_compatibility/document.rb +14 -14
  14. data/lib/mongomapper/rails_compatibility/embedded_document.rb +26 -24
  15. data/lib/mongomapper/support.rb +156 -29
  16. data/lib/mongomapper/validations.rb +69 -47
  17. data/test/custom_matchers.rb +48 -0
  18. data/test/functional/associations/test_belongs_to_polymorphic_proxy.rb +53 -56
  19. data/test/functional/associations/test_belongs_to_proxy.rb +48 -49
  20. data/test/functional/associations/test_many_documents_as_proxy.rb +208 -253
  21. data/test/functional/associations/test_many_embedded_polymorphic_proxy.rb +130 -130
  22. data/test/functional/associations/test_many_embedded_proxy.rb +168 -106
  23. data/test/functional/associations/test_many_polymorphic_proxy.rb +261 -262
  24. data/test/functional/test_binary.rb +21 -0
  25. data/test/functional/test_document.rb +946 -952
  26. data/test/functional/test_embedded_document.rb +98 -0
  27. data/test/functional/test_pagination.rb +87 -80
  28. data/test/functional/test_rails_compatibility.rb +29 -29
  29. data/test/functional/test_validations.rb +262 -172
  30. data/test/models.rb +169 -169
  31. data/test/test_helper.rb +28 -66
  32. data/test/unit/serializers/test_json_serializer.rb +193 -193
  33. data/test/unit/test_document.rb +161 -123
  34. data/test/unit/test_embedded_document.rb +643 -547
  35. data/test/unit/test_finder_options.rb +183 -183
  36. data/test/unit/test_key.rb +175 -247
  37. data/test/unit/test_rails_compatibility.rb +38 -33
  38. data/test/unit/test_serializations.rb +52 -52
  39. data/test/unit/test_support.rb +268 -0
  40. data/test/unit/test_time_zones.rb +40 -0
  41. data/test/unit/test_validations.rb +499 -258
  42. metadata +22 -12
  43. data/History +0 -76
  44. data/mongomapper.gemspec +0 -145
@@ -1,47 +1,69 @@
1
- module MongoMapper
2
- module Validations
3
- class ValidatesUniquenessOf < Validatable::ValidationBase
4
- def valid?(instance)
5
- # TODO: scope
6
- doc = instance.class.find(:first, :conditions => {self.attribute => instance[attribute]}, :limit => 1)
7
- doc.nil? || instance.id == doc.id
8
- end
9
-
10
- def message(instance)
11
- super || "has already been taken"
12
- end
13
- end
14
-
15
- class ValidatesExclusionOf < Validatable::ValidationBase
16
- required_option :within
17
-
18
- def valid?(instance)
19
- value = instance[attribute]
20
- return true if allow_nil && value.nil?
21
- return true if allow_blank && value.blank?
22
-
23
- !within.include?(instance[attribute])
24
- end
25
-
26
- def message(instance)
27
- super || "is reserved"
28
- end
29
- end
30
-
31
- class ValidatesInclusionOf < Validatable::ValidationBase
32
- required_option :within
33
-
34
- def valid?(instance)
35
- value = instance[attribute]
36
- return true if allow_nil && value.nil?
37
- return true if allow_blank && value.blank?
38
-
39
- within.include?(value)
40
- end
41
-
42
- def message(instance)
43
- super || "is not in the list"
44
- end
45
- end
46
- end
47
- end
1
+ module MongoMapper
2
+ module Validations
3
+ module Macros
4
+ def validates_uniqueness_of(*args)
5
+ add_validations(args, MongoMapper::Validations::ValidatesUniquenessOf)
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
+ end
16
+
17
+ class ValidatesUniquenessOf < Validatable::ValidationBase
18
+ option :scope
19
+
20
+ def valid?(instance)
21
+ doc = instance.class.find(:first, :conditions => {self.attribute => instance[attribute]}.merge(scope_conditions(instance)), :limit => 1)
22
+ doc.nil? || instance.id == doc.id
23
+ end
24
+
25
+ def message(instance)
26
+ super || "has already been taken"
27
+ end
28
+
29
+ def scope_conditions(instance)
30
+ return {} unless scope
31
+ Array(scope).inject({}) do |conditions, key|
32
+ conditions.merge(key => instance[key])
33
+ end
34
+ end
35
+ end
36
+
37
+ class ValidatesExclusionOf < Validatable::ValidationBase
38
+ required_option :within
39
+
40
+ def valid?(instance)
41
+ value = instance[attribute]
42
+ return true if allow_nil && value.nil?
43
+ return true if allow_blank && value.blank?
44
+
45
+ !within.include?(instance[attribute])
46
+ end
47
+
48
+ def message(instance)
49
+ super || "is reserved"
50
+ end
51
+ end
52
+
53
+ class ValidatesInclusionOf < Validatable::ValidationBase
54
+ required_option :within
55
+
56
+ def valid?(instance)
57
+ value = instance[attribute]
58
+ return true if allow_nil && value.nil?
59
+ return true if allow_blank && value.blank?
60
+
61
+ within.include?(value)
62
+ end
63
+
64
+ def message(instance)
65
+ super || "is not in the list"
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,48 @@
1
+ module CustomMatchers
2
+ custom_matcher :be_nil do |receiver, matcher, args|
3
+ matcher.positive_failure_message = "Expected #{receiver} to be nil but it wasn't"
4
+ matcher.negative_failure_message = "Expected #{receiver} not to be nil but it was"
5
+ receiver.nil?
6
+ end
7
+
8
+ custom_matcher :be_blank do |receiver, matcher, args|
9
+ matcher.positive_failure_message = "Expected #{receiver} to be blank but it wasn't"
10
+ matcher.negative_failure_message = "Expected #{receiver} not to be blank but it was"
11
+ receiver.blank?
12
+ end
13
+
14
+ custom_matcher :be_true do |receiver, matcher, args|
15
+ matcher.positive_failure_message = "Expected #{receiver} to be true but it wasn't"
16
+ matcher.negative_failure_message = "Expected #{receiver} not to be true but it was"
17
+ receiver.eql?(true)
18
+ end
19
+
20
+ custom_matcher :be_false do |receiver, matcher, args|
21
+ matcher.positive_failure_message = "Expected #{receiver} to be false but it wasn't"
22
+ matcher.negative_failure_message = "Expected #{receiver} not to be false but it was"
23
+ receiver.eql?(false)
24
+ end
25
+
26
+ custom_matcher :be_valid do |receiver, matcher, args|
27
+ matcher.positive_failure_message = "Expected to be valid but it was invalid #{receiver.errors.inspect}"
28
+ matcher.negative_failure_message = "Expected to be invalid but it was valid #{receiver.errors.inspect}"
29
+ receiver.valid?
30
+ end
31
+
32
+ custom_matcher :have_error_on do |receiver, matcher, args|
33
+ receiver.valid?
34
+ attribute = args[0]
35
+ expected_message = args[1]
36
+
37
+ if expected_message.nil?
38
+ matcher.positive_failure_message = "#{receiver} had no errors on #{attribute}"
39
+ matcher.negative_failure_message = "#{receiver} had errors on #{attribute} #{receiver.errors.inspect}"
40
+ !receiver.errors.on(attribute).blank?
41
+ else
42
+ actual = receiver.errors.on(attribute)
43
+ matcher.positive_failure_message = %Q(Expected error on #{attribute} to be "#{expected_message}" but was "#{actual}")
44
+ matcher.negative_failure_message = %Q(Expected error on #{attribute} not to be "#{expected_message}" but was "#{actual}")
45
+ actual == expected_message
46
+ end
47
+ end
48
+ end
@@ -1,57 +1,54 @@
1
- require 'test_helper'
2
- require 'models'
3
-
4
- class BelongsToPolymorphicProxyTest < Test::Unit::TestCase
5
- def setup
6
- clear_all_collections
7
- end
8
-
9
- should "default to nil" do
10
- status = Status.new
11
- status.target.should be_nil
12
- status.target.inspect.should == "nil"
13
- end
14
-
15
- should "be able to replace the association" do
16
- status = Status.new
17
- project = Project.new(:name => "mongomapper")
18
- status.target = project
19
- status.save.should be_true
20
-
21
- from_db = Status.find(status.id)
22
- from_db.target.should_not be_nil
23
- from_db.target.inspect.should_not be_empty
24
- from_db.target_id.should == project.id
25
- from_db.target_type.should == "Project"
26
- from_db.target.name.should == "mongomapper"
27
- end
28
-
29
- should "unset the association" do
30
- status = Status.new
31
- project = Project.new(:name => "mongomapper")
32
- status.target = project
33
- status.save.should be_true
34
-
35
- from_db = Status.find(status.id)
36
- from_db.target = nil
37
- from_db.target_type.should be_nil
38
- from_db.target_id.should be_nil
39
- from_db.target.should be_nil
40
- from_db.target.inspect.should == "nil"
41
- end
42
-
43
- context "association id set but document not found" do
44
- setup do
45
- @status = Status.new
46
- project = Project.new(:name => "mongomapper")
47
- @status.target = project
48
- @status.save.should be_true
49
- project.destroy
50
- end
51
-
52
- should "return nil instead of raising error" do
53
- @status.target.should be_nil
54
- @status.target.inspect.should == "nil"
55
- end
56
- end
1
+ require 'test_helper'
2
+ require 'models'
3
+
4
+ class BelongsToPolymorphicProxyTest < Test::Unit::TestCase
5
+ def setup
6
+ clear_all_collections
7
+ end
8
+
9
+ should "default to nil" do
10
+ status = Status.new
11
+ status.target.nil?.should == true
12
+ status.target.inspect.should == "nil"
13
+ end
14
+
15
+ should "be able to replace the association" do
16
+ status = Status.new
17
+ project = Project.new(:name => "mongomapper")
18
+ status.target = project
19
+ status.save.should be_true
20
+
21
+ from_db = Status.find(status.id)
22
+ from_db.target.nil?.should == false
23
+ from_db.target_id.should == project.id
24
+ from_db.target_type.should == "Project"
25
+ from_db.target.name.should == "mongomapper"
26
+ end
27
+
28
+ should "unset the association" do
29
+ status = Status.new
30
+ project = Project.new(:name => "mongomapper")
31
+ status.target = project
32
+ status.save.should be_true
33
+
34
+ from_db = Status.find(status.id)
35
+ from_db.target = nil
36
+ from_db.target_type.nil?.should == true
37
+ from_db.target_id.nil?.should == true
38
+ from_db.target.nil?.should == true
39
+ end
40
+
41
+ context "association id set but document not found" do
42
+ setup do
43
+ @status = Status.new
44
+ project = Project.new(:name => "mongomapper")
45
+ @status.target = project
46
+ @status.save.should be_true
47
+ project.destroy
48
+ end
49
+
50
+ should "return nil instead of raising error" do
51
+ @status.target.nil?.should == true
52
+ end
53
+ end
57
54
  end
@@ -1,49 +1,48 @@
1
- require 'test_helper'
2
- require 'models'
3
-
4
- class BelongsToProxyTest < Test::Unit::TestCase
5
- def setup
6
- clear_all_collections
7
- end
8
-
9
- should "default to nil" do
10
- status = Status.new
11
- status.project.should be_nil
12
- status.project.inspect.should == "nil"
13
- end
14
-
15
- should "be able to replace the association" do
16
- status = Status.new
17
- project = Project.new(:name => "mongomapper")
18
- status.project = project
19
- status.save.should be_true
20
-
21
- from_db = Status.find(status.id)
22
- from_db.project.should_not be_nil
23
- from_db.project.inspect.should_not be_empty
24
- from_db.project.name.should == "mongomapper"
25
- end
26
-
27
- should "unset the association" do
28
- status = Status.new
29
- project = Project.new(:name => "mongomapper")
30
- status.project = project
31
- status.save.should be_true
32
-
33
- from_db = Status.find(status.id)
34
- from_db.project = nil
35
- from_db.project.should be_nil
36
- from_db.project.inspect.should == "nil"
37
- end
38
-
39
- context "association id set but document not found" do
40
- setup do
41
- @status = Status.new(:name => 'Foo', :project_id => '1234')
42
- end
43
-
44
- should "return nil instead of raising error" do
45
- @status.project.should be_nil
46
- @status.project.inspect.should == "nil"
47
- end
48
- end
49
- end
1
+ require 'test_helper'
2
+ require 'models'
3
+
4
+ class BelongsToProxyTest < Test::Unit::TestCase
5
+ def setup
6
+ clear_all_collections
7
+ end
8
+
9
+ should "default to nil" do
10
+ status = Status.new
11
+ status.project.nil?.should == true
12
+ status.project.inspect.should == "nil"
13
+ end
14
+
15
+ should "be able to replace the association" do
16
+ status = Status.new
17
+ project = Project.new(:name => "mongomapper")
18
+ status.project = project
19
+ status.save.should be_true
20
+
21
+ from_db = Status.find(status.id)
22
+ from_db.project.should_not be_nil
23
+ from_db.project.name.should == "mongomapper"
24
+ end
25
+
26
+ should "unset the association" do
27
+ status = Status.new
28
+ project = Project.new(:name => "mongomapper")
29
+ status.project = project
30
+ status.save.should be_true
31
+
32
+ from_db = Status.find(status.id)
33
+ from_db.project = nil
34
+ from_db.project.nil?.should == true
35
+ from_db.project.inspect.should == "nil"
36
+ end
37
+
38
+ context "association id set but document not found" do
39
+ setup do
40
+ @status = Status.new(:name => 'Foo', :project_id => '1234')
41
+ end
42
+
43
+ should "return nil instead of raising error" do
44
+ @status.project.nil?.should == true
45
+ @status.project.inspect.should == "nil"
46
+ end
47
+ end
48
+ end
@@ -1,254 +1,209 @@
1
- require 'test_helper'
2
- require 'models'
3
-
4
- class ManyDocumentsAsProxyTest < Test::Unit::TestCase
5
- def setup
6
- clear_all_collections
7
- end
8
-
9
- should "default reader to empty array" do
10
- Post.new.comments.should == []
11
- Post.new.comments.inspect.should == "[]"
12
- end
13
-
14
- should "add type and id key to polymorphic class base" do
15
- PostComment.keys.keys.should include('commentable_type')
16
- PostComment.keys.keys.should include('commentable_id')
17
- end
18
-
19
- should "allow adding to association like it was an array" do
20
- post = Post.new
21
- post.comments << PostComment.new(:body => 'foo bar')
22
- post.comments << PostComment.new(:body => 'baz')
23
- post.comments.concat PostComment.new(:body => 'baz')
24
-
25
- post.comments.size.should == 3
26
- end
27
-
28
- should "be able to replace the association" do
29
- post = Post.new
30
-
31
- lambda {
32
- post.comments = [
33
- PostComment.new(:body => 'foo'),
34
- PostComment.new(:body => 'bar'),
35
- PostComment.new(:body => 'baz')
36
- ]
37
- }.should change { PostComment.count }.by(3)
38
-
39
- from_db = Post.find(post.id)
40
- from_db.comments.size.should == 3
41
- from_db.comments[0].body.should == 'foo'
42
- from_db.comments[1].body.should == 'bar'
43
- from_db.comments[2].body.should == 'baz'
44
- end
45
-
46
- context "build" do
47
- should "assign foreign key" do
48
- post = Post.new
49
- comment = post.comments.build
50
- comment.commentable_id.should == post.id
51
- end
52
-
53
- should "assign _type" do
54
- post = Post.new
55
- comment = post.comments.build
56
- comment.commentable_type.should == "Post"
57
- end
58
-
59
- should "allow assigning attributes" do
60
- post = Post.new
61
- comment = post.comments.build(:body => 'foo bar')
62
- comment.body.should == 'foo bar'
63
- end
64
- end
65
-
66
- context "create" do
67
- should "assign foreign key" do
68
- post = Post.new
69
- comment = post.comments.create
70
- comment.commentable_id.should == post.id
71
- end
72
-
73
- should "assign _type" do
74
- post = Post.new
75
- comment = post.comments.create
76
- comment.commentable_type.should == "Post"
77
- end
78
-
79
- should "save record" do
80
- post = Post.new
81
- lambda {
82
- post.comments.create(:body => 'baz')
83
- }.should change { PostComment.count }
84
- end
85
-
86
- should "allow passing attributes" do
87
- post = Post.create
88
- comment = post.comments.create(:body => 'foo bar')
89
- comment.body.should == 'foo bar'
90
- end
91
- end
92
-
93
- context "count" do
94
- should "work scoped to association" do
95
- post = Post.create
96
- 3.times { post.comments.create(:body => 'foo bar') }
97
-
98
- other_post = Post.create
99
- 2.times { other_post.comments.create(:body => 'baz') }
100
-
101
- post.comments.count.should == 3
102
- other_post.comments.count.should == 2
103
- end
104
-
105
- should "work with conditions" do
106
- post = Post.create
107
- post.comments.create(:body => 'foo bar')
108
- post.comments.create(:body => 'baz')
109
- post.comments.create(:body => 'foo bar')
110
-
111
- post.comments.count(:body => 'foo bar').should == 2
112
- end
113
- end
114
-
115
- context "Finding scoped to association" do
116
- setup do
117
- @post = Post.new
118
-
119
- @comment1 = PostComment.create(:body => 'comment1')
120
- @comment2 = PostComment.create(:body => 'comment2')
121
- @comment3 = PostComment.create(:body => 'comment3')
122
- @post.comments = [@comment1, @comment2]
123
- @post.save
124
-
125
- @post2 = Post.create(:body => "post #2")
126
- @comment4 = PostComment.create(:body => 'comment4')
127
- @comment5 = PostComment.create(:body => 'comment5')
128
- @comment6 = PostComment.create(:body => 'comment6')
129
- @post2.comments = [@comment4, @comment5, @comment6]
130
- @post2.save
131
- end
132
-
133
- context "with :all" do
134
- should "work" do
135
- @post.comments.find(:all).should include(@comment1)
136
- @post.comments.find(:all).should include(@comment2)
137
- end
138
-
139
- should "work with conditions" do
140
- comments = @post.comments.find(:all, :conditions => {:body => 'comment1'})
141
- comments.should == [@comment1]
142
- end
143
-
144
- should "work with order" do
145
- comments = @post.comments.find(:all, :order => 'body desc')
146
- comments.should == [@comment2, @comment1]
147
- end
148
- end
149
-
150
- context "with #all" do
151
- should "work" do
152
- @post.comments.all.should == [@comment1, @comment2]
153
- end
154
-
155
- should "work with conditions" do
156
- comments = @post.comments.all(:conditions => {:body => 'comment1'})
157
- comments.should == [@comment1]
158
- end
159
-
160
- should "work with order" do
161
- comments = @post.comments.all(:order => '$natural desc')
162
- comments.should == [@comment2, @comment1]
163
- end
164
- end
165
-
166
- context "with :first" do
167
- should "work" do
168
- lambda {@post.comments.find(:first)}.should_not raise_error
169
- end
170
-
171
- should "work with conditions" do
172
- comment = @post.comments.find(:first, :conditions => {:body => 'comment2'})
173
- comment.body.should == 'comment2'
174
- end
175
- end
176
-
177
- context "with #first" do
178
- should "work" do
179
- @post.comments.first.should == @comment1
180
- end
181
-
182
- should "work with conditions" do
183
- comment = @post.comments.first(:conditions => {:body => 'comment2'}, :order => 'body desc')
184
- comment.should == @comment2
185
- end
186
- end
187
-
188
- context "with :last" do
189
- should "work" do
190
- @post.comments.find(:last, :order => 'created_at asc').should == @comment2
191
- end
192
-
193
- should "work with conditions" do
194
- post = @post.comments.find(:last, :conditions => {:body => 'comment1'})
195
- post.body.should == 'comment1'
196
- end
197
- end
198
-
199
- context "with #last" do
200
- should "work" do
201
- @post.comments.last.should == @comment2
202
- end
203
-
204
- should "work with conditions" do
205
- comment = @post.comments.last(:conditions => {:body => 'comment1'})
206
- comment.should == @comment1
207
- end
208
- end
209
-
210
- context "with one id" do
211
- should "work for id in association" do
212
- @post.comments.find(@comment2.id).should == @comment2
213
- end
214
-
215
- should "not work for id not in association" do
216
- lambda {
217
- @post.comments.find(@comment5.id)
218
- }.should raise_error(MongoMapper::DocumentNotFound)
219
- end
220
- end
221
-
222
- context "with multiple ids" do
223
- should "work for ids in association" do
224
- posts = @post.comments.find(@comment1.id, @comment2.id)
225
- posts.should == [@comment1, @comment2]
226
- end
227
-
228
- should "not work for ids not in association" do
229
- lambda {
230
- @post.comments.find(@comment1.id, @comment2.id, @comment4.id)
231
- }.should raise_error(MongoMapper::DocumentNotFound)
232
- end
233
- end
234
-
235
- context "with #paginate" do
236
- setup do
237
- @comments = @post2.comments.paginate(:per_page => 2, :page => 1, :order => 'created_at asc')
238
- end
239
-
240
- should "return total pages" do
241
- @comments.total_pages.should == 2
242
- end
243
-
244
- should "return total entries" do
245
- @comments.total_entries.should == 3
246
- end
247
-
248
- should "return the subject" do
249
- @comments.should include(@comment4)
250
- @comments.should include(@comment5)
251
- end
252
- end
253
- end
1
+ require 'test_helper'
2
+ require 'models'
3
+
4
+ class ManyDocumentsAsProxyTest < Test::Unit::TestCase
5
+ def setup
6
+ clear_all_collections
7
+ end
8
+
9
+ should "default reader to empty array" do
10
+ Post.new.comments.should == []
11
+ end
12
+
13
+ should "add type and id key to polymorphic class base" do
14
+ PostComment.keys.keys.should include('commentable_type')
15
+ PostComment.keys.keys.should include('commentable_id')
16
+ end
17
+
18
+ should "allow adding to association like it was an array" do
19
+ post = Post.new
20
+ post.comments << PostComment.new(:body => 'foo bar')
21
+ post.comments << PostComment.new(:body => 'baz')
22
+ post.comments.concat PostComment.new(:body => 'baz')
23
+
24
+ post.comments.size.should == 3
25
+ end
26
+
27
+ should "be able to replace the association" do
28
+ post = Post.new
29
+
30
+ lambda {
31
+ post.comments = [
32
+ PostComment.new(:body => 'foo'),
33
+ PostComment.new(:body => 'bar'),
34
+ PostComment.new(:body => 'baz')
35
+ ]
36
+ }.should change { PostComment.count }.by(3)
37
+
38
+ from_db = Post.find(post.id)
39
+ from_db.comments.size.should == 3
40
+ from_db.comments[0].body.should == 'foo'
41
+ from_db.comments[1].body.should == 'bar'
42
+ from_db.comments[2].body.should == 'baz'
43
+ end
44
+
45
+ context "build" do
46
+ should "assign foreign key" do
47
+ post = Post.new
48
+ comment = post.comments.build
49
+ comment.commentable_id.should == post.id
50
+ end
51
+
52
+ should "assign _type" do
53
+ post = Post.new
54
+ comment = post.comments.build
55
+ comment.commentable_type.should == "Post"
56
+ end
57
+
58
+ should "allow assigning attributes" do
59
+ post = Post.new
60
+ comment = post.comments.build(:body => 'foo bar')
61
+ comment.body.should == 'foo bar'
62
+ end
63
+ end
64
+
65
+ context "create" do
66
+ should "assign foreign key" do
67
+ post = Post.new
68
+ comment = post.comments.create
69
+ comment.commentable_id.should == post.id
70
+ end
71
+
72
+ should "assign _type" do
73
+ post = Post.new
74
+ comment = post.comments.create
75
+ comment.commentable_type.should == "Post"
76
+ end
77
+
78
+ should "save record" do
79
+ post = Post.new
80
+ lambda {
81
+ post.comments.create(:body => 'baz')
82
+ }.should change { PostComment.count }
83
+ end
84
+
85
+ should "allow passing attributes" do
86
+ post = Post.create
87
+ comment = post.comments.create(:body => 'foo bar')
88
+ comment.body.should == 'foo bar'
89
+ end
90
+ end
91
+
92
+ context "count" do
93
+ should "work scoped to association" do
94
+ post = Post.create
95
+ 3.times { post.comments.create(:body => 'foo bar') }
96
+
97
+ other_post = Post.create
98
+ 2.times { other_post.comments.create(:body => 'baz') }
99
+
100
+ post.comments.count.should == 3
101
+ other_post.comments.count.should == 2
102
+ end
103
+
104
+ should "work with conditions" do
105
+ post = Post.create
106
+ post.comments.create(:body => 'foo bar')
107
+ post.comments.create(:body => 'baz')
108
+ post.comments.create(:body => 'foo bar')
109
+
110
+ post.comments.count(:body => 'foo bar').should == 2
111
+ end
112
+ end
113
+
114
+ context "Finding scoped to association" do
115
+ setup do
116
+ @post = Post.new
117
+
118
+ @comment1 = PostComment.create(:body => 'comment1')
119
+ @comment2 = PostComment.create(:body => 'comment2')
120
+ @comment3 = PostComment.create(:body => 'comment3')
121
+ @post.comments = [@comment1, @comment2]
122
+ @post.save
123
+
124
+ @post2 = Post.create(:body => "post #2")
125
+ @comment4 = PostComment.create(:body => 'comment4')
126
+ @comment5 = PostComment.create(:body => 'comment5')
127
+ @comment6 = PostComment.create(:body => 'comment6')
128
+ @post2.comments = [@comment4, @comment5, @comment6]
129
+ @post2.save
130
+ end
131
+
132
+ context "with :all" do
133
+ should "work" do
134
+ @post.comments.find(:all).should include(@comment1)
135
+ @post.comments.find(:all).should include(@comment2)
136
+ end
137
+
138
+ should "work with conditions" do
139
+ comments = @post.comments.find(:all, :conditions => {:body => 'comment1'})
140
+ comments.should == [@comment1]
141
+ end
142
+
143
+ should "work with order" do
144
+ comments = @post.comments.find(:all, :order => 'body desc')
145
+ comments.should == [@comment2, @comment1]
146
+ end
147
+ end
148
+
149
+ context "with #all" do
150
+ should "work" do
151
+ @post.comments.all.should == [@comment1, @comment2]
152
+ end
153
+
154
+ should "work with conditions" do
155
+ comments = @post.comments.all(:conditions => {:body => 'comment1'})
156
+ comments.should == [@comment1]
157
+ end
158
+
159
+ should "work with order" do
160
+ comments = @post.comments.all(:order => '$natural desc')
161
+ comments.should == [@comment2, @comment1]
162
+ end
163
+ end
164
+
165
+ context "with one id" do
166
+ should "work for id in association" do
167
+ @post.comments.find(@comment2.id).should == @comment2
168
+ end
169
+
170
+ should "not work for id not in association" do
171
+ lambda {
172
+ @post.comments.find(@comment5.id)
173
+ }.should raise_error(MongoMapper::DocumentNotFound)
174
+ end
175
+ end
176
+
177
+ context "with multiple ids" do
178
+ should "work for ids in association" do
179
+ posts = @post.comments.find(@comment1.id, @comment2.id)
180
+ posts.should == [@comment1, @comment2]
181
+ end
182
+
183
+ should "not work for ids not in association" do
184
+ lambda {
185
+ @post.comments.find(@comment1.id, @comment2.id, @comment4.id)
186
+ }.should raise_error(MongoMapper::DocumentNotFound)
187
+ end
188
+ end
189
+
190
+ context "with #paginate" do
191
+ setup do
192
+ @comments = @post2.comments.paginate(:per_page => 2, :page => 1, :order => 'created_at asc')
193
+ end
194
+
195
+ should "return total pages" do
196
+ @comments.total_pages.should == 2
197
+ end
198
+
199
+ should "return total entries" do
200
+ @comments.total_entries.should == 3
201
+ end
202
+
203
+ should "return the subject" do
204
+ @comments.should include(@comment4)
205
+ @comments.should include(@comment5)
206
+ end
207
+ end
208
+ end
254
209
  end