danielharan-mongo_mapper 0.6.5

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 (74) hide show
  1. data/.gitignore +10 -0
  2. data/LICENSE +20 -0
  3. data/README.rdoc +53 -0
  4. data/Rakefile +55 -0
  5. data/VERSION +1 -0
  6. data/bin/mmconsole +60 -0
  7. data/lib/mongo_mapper.rb +134 -0
  8. data/lib/mongo_mapper/associations.rb +183 -0
  9. data/lib/mongo_mapper/associations/base.rb +110 -0
  10. data/lib/mongo_mapper/associations/belongs_to_polymorphic_proxy.rb +34 -0
  11. data/lib/mongo_mapper/associations/belongs_to_proxy.rb +22 -0
  12. data/lib/mongo_mapper/associations/many_documents_as_proxy.rb +25 -0
  13. data/lib/mongo_mapper/associations/many_documents_proxy.rb +127 -0
  14. data/lib/mongo_mapper/associations/many_embedded_polymorphic_proxy.rb +33 -0
  15. data/lib/mongo_mapper/associations/many_embedded_proxy.rb +53 -0
  16. data/lib/mongo_mapper/associations/many_polymorphic_proxy.rb +11 -0
  17. data/lib/mongo_mapper/associations/many_proxy.rb +6 -0
  18. data/lib/mongo_mapper/associations/proxy.rb +80 -0
  19. data/lib/mongo_mapper/callbacks.rb +109 -0
  20. data/lib/mongo_mapper/dirty.rb +136 -0
  21. data/lib/mongo_mapper/document.rb +481 -0
  22. data/lib/mongo_mapper/dynamic_finder.rb +35 -0
  23. data/lib/mongo_mapper/embedded_document.rb +386 -0
  24. data/lib/mongo_mapper/finder_options.rb +133 -0
  25. data/lib/mongo_mapper/key.rb +36 -0
  26. data/lib/mongo_mapper/observing.rb +50 -0
  27. data/lib/mongo_mapper/pagination.rb +53 -0
  28. data/lib/mongo_mapper/rails_compatibility/document.rb +15 -0
  29. data/lib/mongo_mapper/rails_compatibility/embedded_document.rb +27 -0
  30. data/lib/mongo_mapper/serialization.rb +54 -0
  31. data/lib/mongo_mapper/serializers/json_serializer.rb +92 -0
  32. data/lib/mongo_mapper/support.rb +193 -0
  33. data/lib/mongo_mapper/validations.rb +41 -0
  34. data/mongo_mapper.gemspec +171 -0
  35. data/specs.watchr +32 -0
  36. data/test/NOTE_ON_TESTING +1 -0
  37. data/test/functional/associations/test_belongs_to_polymorphic_proxy.rb +55 -0
  38. data/test/functional/associations/test_belongs_to_proxy.rb +48 -0
  39. data/test/functional/associations/test_many_documents_as_proxy.rb +246 -0
  40. data/test/functional/associations/test_many_embedded_polymorphic_proxy.rb +156 -0
  41. data/test/functional/associations/test_many_embedded_proxy.rb +196 -0
  42. data/test/functional/associations/test_many_polymorphic_proxy.rb +339 -0
  43. data/test/functional/associations/test_many_proxy.rb +384 -0
  44. data/test/functional/test_associations.rb +44 -0
  45. data/test/functional/test_binary.rb +18 -0
  46. data/test/functional/test_callbacks.rb +85 -0
  47. data/test/functional/test_dirty.rb +159 -0
  48. data/test/functional/test_document.rb +1180 -0
  49. data/test/functional/test_embedded_document.rb +125 -0
  50. data/test/functional/test_logger.rb +20 -0
  51. data/test/functional/test_pagination.rb +95 -0
  52. data/test/functional/test_rails_compatibility.rb +25 -0
  53. data/test/functional/test_string_id_compatibility.rb +72 -0
  54. data/test/functional/test_validations.rb +369 -0
  55. data/test/models.rb +271 -0
  56. data/test/support/custom_matchers.rb +55 -0
  57. data/test/support/timing.rb +16 -0
  58. data/test/test_helper.rb +27 -0
  59. data/test/unit/serializers/test_json_serializer.rb +189 -0
  60. data/test/unit/test_association_base.rb +166 -0
  61. data/test/unit/test_document.rb +204 -0
  62. data/test/unit/test_dynamic_finder.rb +125 -0
  63. data/test/unit/test_embedded_document.rb +718 -0
  64. data/test/unit/test_finder_options.rb +296 -0
  65. data/test/unit/test_key.rb +172 -0
  66. data/test/unit/test_mongo_mapper.rb +65 -0
  67. data/test/unit/test_observing.rb +101 -0
  68. data/test/unit/test_pagination.rb +113 -0
  69. data/test/unit/test_rails_compatibility.rb +49 -0
  70. data/test/unit/test_serializations.rb +52 -0
  71. data/test/unit/test_support.rb +342 -0
  72. data/test/unit/test_time_zones.rb +40 -0
  73. data/test/unit/test_validations.rb +503 -0
  74. metadata +233 -0
@@ -0,0 +1,41 @@
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
+ end
8
+
9
+ class ValidatesUniquenessOf < Validatable::ValidationBase
10
+ option :scope, :case_sensitive
11
+ default :case_sensitive => true
12
+
13
+ def valid?(instance)
14
+ value = instance[attribute]
15
+ return true if allow_blank && value.blank?
16
+ base_conditions = case_sensitive ? {self.attribute => value} : {}
17
+ doc = instance.class.first(base_conditions.merge(scope_conditions(instance)).merge(where_conditions(instance)))
18
+ doc.nil? || instance._id == doc._id
19
+ end
20
+
21
+ def message(instance)
22
+ super || "has already been taken"
23
+ end
24
+
25
+ def scope_conditions(instance)
26
+ return {} unless scope
27
+ Array(scope).inject({}) do |conditions, key|
28
+ conditions.merge(key => instance[key])
29
+ end
30
+ end
31
+
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
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,171 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{danielharan-mongo_mapper}
8
+ s.version = "0.6.5"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["John Nunemaker"]
12
+ s.date = %q{2009-12-01}
13
+ s.default_executable = %q{mmconsole}
14
+ s.email = %q{chebuctonian@gmail.com}
15
+ s.executables = ["mmconsole"]
16
+ s.extra_rdoc_files = [
17
+ "LICENSE",
18
+ "README.rdoc"
19
+ ]
20
+ s.files = [
21
+ ".gitignore",
22
+ "LICENSE",
23
+ "README.rdoc",
24
+ "Rakefile",
25
+ "VERSION",
26
+ "bin/mmconsole",
27
+ "lib/mongo_mapper.rb",
28
+ "lib/mongo_mapper/associations.rb",
29
+ "lib/mongo_mapper/associations/base.rb",
30
+ "lib/mongo_mapper/associations/belongs_to_polymorphic_proxy.rb",
31
+ "lib/mongo_mapper/associations/belongs_to_proxy.rb",
32
+ "lib/mongo_mapper/associations/many_documents_as_proxy.rb",
33
+ "lib/mongo_mapper/associations/many_documents_proxy.rb",
34
+ "lib/mongo_mapper/associations/many_embedded_polymorphic_proxy.rb",
35
+ "lib/mongo_mapper/associations/many_embedded_proxy.rb",
36
+ "lib/mongo_mapper/associations/many_polymorphic_proxy.rb",
37
+ "lib/mongo_mapper/associations/many_proxy.rb",
38
+ "lib/mongo_mapper/associations/proxy.rb",
39
+ "lib/mongo_mapper/callbacks.rb",
40
+ "lib/mongo_mapper/dirty.rb",
41
+ "lib/mongo_mapper/document.rb",
42
+ "lib/mongo_mapper/dynamic_finder.rb",
43
+ "lib/mongo_mapper/embedded_document.rb",
44
+ "lib/mongo_mapper/finder_options.rb",
45
+ "lib/mongo_mapper/key.rb",
46
+ "lib/mongo_mapper/observing.rb",
47
+ "lib/mongo_mapper/pagination.rb",
48
+ "lib/mongo_mapper/rails_compatibility/document.rb",
49
+ "lib/mongo_mapper/rails_compatibility/embedded_document.rb",
50
+ "lib/mongo_mapper/serialization.rb",
51
+ "lib/mongo_mapper/serializers/json_serializer.rb",
52
+ "lib/mongo_mapper/support.rb",
53
+ "lib/mongo_mapper/validations.rb",
54
+ "mongo_mapper.gemspec",
55
+ "specs.watchr",
56
+ "test/NOTE_ON_TESTING",
57
+ "test/functional/associations/test_belongs_to_polymorphic_proxy.rb",
58
+ "test/functional/associations/test_belongs_to_proxy.rb",
59
+ "test/functional/associations/test_many_documents_as_proxy.rb",
60
+ "test/functional/associations/test_many_embedded_polymorphic_proxy.rb",
61
+ "test/functional/associations/test_many_embedded_proxy.rb",
62
+ "test/functional/associations/test_many_polymorphic_proxy.rb",
63
+ "test/functional/associations/test_many_proxy.rb",
64
+ "test/functional/test_associations.rb",
65
+ "test/functional/test_binary.rb",
66
+ "test/functional/test_callbacks.rb",
67
+ "test/functional/test_dirty.rb",
68
+ "test/functional/test_document.rb",
69
+ "test/functional/test_embedded_document.rb",
70
+ "test/functional/test_logger.rb",
71
+ "test/functional/test_pagination.rb",
72
+ "test/functional/test_rails_compatibility.rb",
73
+ "test/functional/test_string_id_compatibility.rb",
74
+ "test/functional/test_validations.rb",
75
+ "test/models.rb",
76
+ "test/support/custom_matchers.rb",
77
+ "test/support/timing.rb",
78
+ "test/test_helper.rb",
79
+ "test/unit/serializers/test_json_serializer.rb",
80
+ "test/unit/test_association_base.rb",
81
+ "test/unit/test_document.rb",
82
+ "test/unit/test_dynamic_finder.rb",
83
+ "test/unit/test_embedded_document.rb",
84
+ "test/unit/test_finder_options.rb",
85
+ "test/unit/test_key.rb",
86
+ "test/unit/test_mongo_mapper.rb",
87
+ "test/unit/test_observing.rb",
88
+ "test/unit/test_pagination.rb",
89
+ "test/unit/test_rails_compatibility.rb",
90
+ "test/unit/test_serializations.rb",
91
+ "test/unit/test_support.rb",
92
+ "test/unit/test_time_zones.rb",
93
+ "test/unit/test_validations.rb"
94
+ ]
95
+ s.homepage = %q{http://github.com/jnunemaker/mongomapper}
96
+ s.rdoc_options = ["--charset=UTF-8"]
97
+ s.require_paths = ["lib"]
98
+ s.rubygems_version = %q{1.3.5}
99
+ s.summary = %q{Awesome gem for modeling your domain and storing it in mongo}
100
+ s.test_files = [
101
+ "test/functional/associations/test_belongs_to_polymorphic_proxy.rb",
102
+ "test/functional/associations/test_belongs_to_proxy.rb",
103
+ "test/functional/associations/test_many_documents_as_proxy.rb",
104
+ "test/functional/associations/test_many_embedded_polymorphic_proxy.rb",
105
+ "test/functional/associations/test_many_embedded_proxy.rb",
106
+ "test/functional/associations/test_many_polymorphic_proxy.rb",
107
+ "test/functional/associations/test_many_proxy.rb",
108
+ "test/functional/test_associations.rb",
109
+ "test/functional/test_binary.rb",
110
+ "test/functional/test_callbacks.rb",
111
+ "test/functional/test_dirty.rb",
112
+ "test/functional/test_document.rb",
113
+ "test/functional/test_embedded_document.rb",
114
+ "test/functional/test_logger.rb",
115
+ "test/functional/test_pagination.rb",
116
+ "test/functional/test_rails_compatibility.rb",
117
+ "test/functional/test_string_id_compatibility.rb",
118
+ "test/functional/test_validations.rb",
119
+ "test/models.rb",
120
+ "test/support/custom_matchers.rb",
121
+ "test/support/timing.rb",
122
+ "test/test_helper.rb",
123
+ "test/unit/serializers/test_json_serializer.rb",
124
+ "test/unit/test_association_base.rb",
125
+ "test/unit/test_document.rb",
126
+ "test/unit/test_dynamic_finder.rb",
127
+ "test/unit/test_embedded_document.rb",
128
+ "test/unit/test_finder_options.rb",
129
+ "test/unit/test_key.rb",
130
+ "test/unit/test_mongo_mapper.rb",
131
+ "test/unit/test_observing.rb",
132
+ "test/unit/test_pagination.rb",
133
+ "test/unit/test_rails_compatibility.rb",
134
+ "test/unit/test_serializations.rb",
135
+ "test/unit/test_support.rb",
136
+ "test/unit/test_time_zones.rb",
137
+ "test/unit/test_validations.rb"
138
+ ]
139
+
140
+ if s.respond_to? :specification_version then
141
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
142
+ s.specification_version = 3
143
+
144
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
145
+ s.add_runtime_dependency(%q<activesupport>, [">= 2.3"])
146
+ s.add_runtime_dependency(%q<mongo>, ["= 0.18"])
147
+ s.add_runtime_dependency(%q<jnunemaker-validatable>, ["= 1.8.1"])
148
+ s.add_development_dependency(%q<jnunemaker-matchy>, ["= 0.4.0"])
149
+ s.add_development_dependency(%q<shoulda>, ["= 2.10.2"])
150
+ s.add_development_dependency(%q<timecop>, ["= 0.3.1"])
151
+ s.add_development_dependency(%q<mocha>, ["= 0.9.8"])
152
+ else
153
+ s.add_dependency(%q<activesupport>, [">= 2.3"])
154
+ s.add_dependency(%q<mongo>, ["= 0.18"])
155
+ s.add_dependency(%q<jnunemaker-validatable>, ["= 1.8.1"])
156
+ s.add_dependency(%q<jnunemaker-matchy>, ["= 0.4.0"])
157
+ s.add_dependency(%q<shoulda>, ["= 2.10.2"])
158
+ s.add_dependency(%q<timecop>, ["= 0.3.1"])
159
+ s.add_dependency(%q<mocha>, ["= 0.9.8"])
160
+ end
161
+ else
162
+ s.add_dependency(%q<activesupport>, [">= 2.3"])
163
+ s.add_dependency(%q<mongo>, ["= 0.18"])
164
+ s.add_dependency(%q<jnunemaker-validatable>, ["= 1.8.1"])
165
+ s.add_dependency(%q<jnunemaker-matchy>, ["= 0.4.0"])
166
+ s.add_dependency(%q<shoulda>, ["= 2.10.2"])
167
+ s.add_dependency(%q<timecop>, ["= 0.3.1"])
168
+ s.add_dependency(%q<mocha>, ["= 0.9.8"])
169
+ end
170
+ end
171
+
@@ -0,0 +1,32 @@
1
+ def run(cmd)
2
+ puts(cmd)
3
+ system(cmd)
4
+ end
5
+
6
+ def run_test_file(file)
7
+ run %Q(ruby -I"lib:test" -rubygems #{file})
8
+ end
9
+
10
+ def run_all_tests
11
+ run "rake test"
12
+ end
13
+
14
+ def related_test_files(path)
15
+ Dir['test/**/*.rb'].select { |file| file =~ /test_#{File.basename(path)}/ }
16
+ end
17
+
18
+ watch('test/test_helper\.rb') { run_all_tests }
19
+ watch('test/.*/test_.*\.rb') { |m| run_test_file(m[0]) }
20
+ watch('lib/.*') do |m|
21
+ related_test_files(m[0]).each { |file| run_test_file(file) }
22
+ end
23
+
24
+ # Ctrl-\
25
+ Signal.trap('QUIT') do
26
+ puts " --- Running all tests ---\n\n"
27
+ run_all_tests
28
+ end
29
+
30
+ # Ctrl-C
31
+ Signal.trap('INT') { abort("\n") }
32
+
@@ -0,0 +1 @@
1
+ I am doing my best to keep unit and functional tests separate. As I see them, functional tests hit the database and should never care about internals. Unit tests do not hit the database.
@@ -0,0 +1,55 @@
1
+ require 'test_helper'
2
+ require 'models'
3
+
4
+ class BelongsToPolymorphicProxyTest < Test::Unit::TestCase
5
+ def setup
6
+ Status.collection.remove
7
+ Project.collection.remove
8
+ end
9
+
10
+ should "default to nil" do
11
+ status = Status.new
12
+ status.target.nil?.should be_true
13
+ status.target.inspect.should == "nil"
14
+ end
15
+
16
+ should "be able to replace the association" do
17
+ status = Status.new(:name => 'Foo!')
18
+ project = Project.new(:name => "mongomapper")
19
+ status.target = project
20
+ status.save.should be_true
21
+
22
+ status = status.reload
23
+ status.target.nil?.should be_false
24
+ status.target_id.should == project._id
25
+ status.target_type.should == "Project"
26
+ status.target.name.should == "mongomapper"
27
+ end
28
+
29
+ should "unset the association" do
30
+ status = Status.new(:name => 'Foo!')
31
+ project = Project.new(:name => "mongomapper")
32
+ status.target = project
33
+ status.save.should be_true
34
+
35
+ status = status.reload
36
+ status.target = nil
37
+ status.target_type.nil?.should be_true
38
+ status.target_id.nil?.should be_true
39
+ status.target.nil?.should be_true
40
+ end
41
+
42
+ context "association id set but document not found" do
43
+ setup do
44
+ @status = Status.new(:name => 'Foo!')
45
+ project = Project.new(:name => "mongomapper")
46
+ @status.target = project
47
+ @status.save.should be_true
48
+ project.destroy
49
+ end
50
+
51
+ should "return nil instead of raising error" do
52
+ @status.target.nil?.should be_true
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,48 @@
1
+ require 'test_helper'
2
+ require 'models'
3
+
4
+ class BelongsToProxyTest < Test::Unit::TestCase
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
18
+ end
19
+
20
+ should "default to nil" do
21
+ @comment_class.new.post.nil?.should be_true
22
+ end
23
+
24
+ should "be able to replace the association" do
25
+ post = @post_class.new(:name => 'mongomapper')
26
+ comment = @comment_class.new(:name => 'Foo!', :post => post)
27
+ comment.save.should be_true
28
+
29
+ comment = comment.reload
30
+ comment.post.should == post
31
+ comment.post.nil?.should be_false
32
+ end
33
+
34
+ should "unset the association" do
35
+ post = @post_class.new(:name => 'mongomapper')
36
+ comment = @comment_class.new(:name => 'Foo!', :post => post)
37
+ comment.save.should be_true
38
+
39
+ comment = comment.reload
40
+ comment.post = nil
41
+ comment.post.nil?.should be_true
42
+ end
43
+
44
+ should "return nil if id set but document not found" do
45
+ id = Mongo::ObjectID.new
46
+ @comment_class.new(:name => 'Foo', :post_id => id).post.nil?.should be_true
47
+ end
48
+ end
@@ -0,0 +1,246 @@
1
+ require 'test_helper'
2
+ require 'models'
3
+
4
+ class ManyDocumentsAsProxyTest < Test::Unit::TestCase
5
+ def setup
6
+ Post.collection.remove
7
+ PostComment.collection.remove
8
+ end
9
+
10
+ should "default reader to empty array" do
11
+ Post.new.comments.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
+ post = post.reload
40
+ post.comments.size.should == 3
41
+ bodies = post.comments.collect(&:body)
42
+ bodies.should include('foo')
43
+ bodies.should include('bar')
44
+ bodies.should include('baz')
45
+ end
46
+
47
+ context "build" do
48
+ should "assign foreign key" do
49
+ post = Post.new
50
+ comment = post.comments.build
51
+ comment.commentable_id.should == post._id
52
+ end
53
+
54
+ should "assign _type" do
55
+ post = Post.new
56
+ comment = post.comments.build
57
+ comment.commentable_type.should == "Post"
58
+ end
59
+
60
+ should "allow assigning attributes" do
61
+ post = Post.new
62
+ comment = post.comments.build(:body => 'foo bar')
63
+ comment.body.should == 'foo bar'
64
+ end
65
+ end
66
+
67
+ context "create" do
68
+ should "assign foreign key" do
69
+ post = Post.new
70
+ comment = post.comments.create
71
+ comment.commentable_id.should == post._id
72
+ end
73
+
74
+ should "assign _type" do
75
+ post = Post.new
76
+ comment = post.comments.create
77
+ comment.commentable_type.should == "Post"
78
+ end
79
+
80
+ should "save record" do
81
+ post = Post.new
82
+ lambda {
83
+ post.comments.create(:body => 'baz')
84
+ }.should change { PostComment.count }
85
+ end
86
+
87
+ should "allow passing attributes" do
88
+ post = Post.create
89
+ comment = post.comments.create(:body => 'foo bar')
90
+ comment.body.should == 'foo bar'
91
+ end
92
+ end
93
+
94
+ context "count" do
95
+ should "work scoped to association" do
96
+ post = Post.create
97
+ 3.times { post.comments.create(:body => 'foo bar') }
98
+
99
+ other_post = Post.create
100
+ 2.times { other_post.comments.create(:body => 'baz') }
101
+
102
+ post.comments.count.should == 3
103
+ other_post.comments.count.should == 2
104
+ end
105
+
106
+ should "work with conditions" do
107
+ post = Post.create
108
+ post.comments.create(:body => 'foo bar')
109
+ post.comments.create(:body => 'baz')
110
+ post.comments.create(:body => 'foo bar')
111
+
112
+ post.comments.count(:body => 'foo bar').should == 2
113
+ end
114
+ end
115
+
116
+ context "Finding scoped to association" do
117
+ setup do
118
+ @post = Post.new
119
+
120
+ @comment1 = PostComment.create(:body => 'comment1', :name => 'John')
121
+ @comment2 = PostComment.create(:body => 'comment2', :name => 'Steve')
122
+ @comment3 = PostComment.create(:body => 'comment3', :name => 'John')
123
+ @post.comments = [@comment1, @comment2]
124
+ @post.save
125
+
126
+ @post2 = Post.create(:body => "post #2")
127
+ @comment4 = PostComment.create(:body => 'comment1', :name => 'Chas')
128
+ @comment5 = PostComment.create(:body => 'comment2', :name => 'Dan')
129
+ @comment6 = PostComment.create(:body => 'comment3', :name => 'Ed')
130
+ @post2.comments = [@comment4, @comment5, @comment6]
131
+ @post2.save
132
+ end
133
+
134
+ context "with :all" do
135
+ should "work" do
136
+ @post.comments.find(:all).should include(@comment1)
137
+ @post.comments.find(:all).should include(@comment2)
138
+ end
139
+
140
+ should "work with conditions" do
141
+ comments = @post.comments.find(:all, :body => 'comment1')
142
+ comments.should == [@comment1]
143
+ end
144
+
145
+ should "work with order" do
146
+ comments = @post.comments.find(:all, :order => 'body desc')
147
+ comments.should == [@comment2, @comment1]
148
+ end
149
+ end
150
+
151
+ context "with #all" do
152
+ should "work" do
153
+ @post.comments.all.should include(@comment1)
154
+ @post.comments.all.should include(@comment2)
155
+ end
156
+
157
+ should "work with conditions" do
158
+ comments = @post.comments.all(:body => 'comment1')
159
+ comments.should == [@comment1]
160
+ end
161
+
162
+ should "work with order" do
163
+ comments = @post.comments.all(:order => 'body desc')
164
+ comments.should == [@comment2, @comment1]
165
+ end
166
+ end
167
+
168
+ context "with one id" do
169
+ should "work for id in association" do
170
+ @post.comments.find(@comment2._id).should == @comment2
171
+ end
172
+
173
+ should "not work for id not in association" do
174
+ lambda {
175
+ @post.comments.find!(@comment5._id)
176
+ }.should raise_error(MongoMapper::DocumentNotFound)
177
+ end
178
+ end
179
+
180
+ context "with multiple ids" do
181
+ should "work for ids in association" do
182
+ posts = @post.comments.find!(@comment1._id, @comment2._id)
183
+ posts.should == [@comment1, @comment2]
184
+ end
185
+
186
+ should "not work for ids not in association" do
187
+ lambda {
188
+ @post.comments.find!(@comment1._id, @comment2._id, @comment4._id)
189
+ }.should raise_error(MongoMapper::DocumentNotFound)
190
+ end
191
+ end
192
+
193
+ context "dynamic finders" do
194
+ should "work with single key" do
195
+ @post.comments.find_by_body('comment1').should == @comment1
196
+ @post2.comments.find_by_body('comment1').should == @comment4
197
+ end
198
+
199
+ should "work with multiple keys" do
200
+ @post.comments.find_by_body_and_name('comment1', 'John').should == @comment1
201
+ @post.comments.find_by_body_and_name('comment1', 'Frank').should be_nil
202
+ end
203
+
204
+ should "raise error when using !" do
205
+ lambda {
206
+ @post.comments.find_by_body!('asdf')
207
+ }.should raise_error(MongoMapper::DocumentNotFound)
208
+ end
209
+
210
+ context "find_or_create_by" do
211
+ should "not create document if found" do
212
+ lambda {
213
+ comment = @post.comments.find_or_create_by_name('Steve')
214
+ comment.commentable.should == @post
215
+ comment.should == @comment2
216
+ }.should_not change { PostComment.count }
217
+ end
218
+
219
+ should "create document if not found" do
220
+ lambda {
221
+ @post.comments.find_or_create_by_name('Chas')
222
+ }.should change { PostComment.count }.by(1)
223
+ end
224
+ end
225
+ end
226
+
227
+ context "with #paginate" do
228
+ setup do
229
+ @comments = @post2.comments.paginate(:per_page => 2, :page => 1, :order => 'name')
230
+ end
231
+
232
+ should "return total pages" do
233
+ @comments.total_pages.should == 2
234
+ end
235
+
236
+ should "return total entries" do
237
+ @comments.total_entries.should == 3
238
+ end
239
+
240
+ should "return the subject" do
241
+ @comments.should include(@comment4)
242
+ @comments.should include(@comment5)
243
+ end
244
+ end
245
+ end
246
+ end