mongo_mapper-unstable 2009.12.30 → 2010.1.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. data/README.rdoc +2 -17
  2. data/Rakefile +1 -1
  3. data/VERSION +1 -1
  4. data/lib/mongo_mapper/associations/base.rb +19 -10
  5. data/lib/mongo_mapper/associations/in_array_proxy.rb +137 -0
  6. data/lib/mongo_mapper/associations/one_proxy.rb +64 -0
  7. data/lib/mongo_mapper/associations/proxy.rb +7 -4
  8. data/lib/mongo_mapper/associations.rb +11 -3
  9. data/lib/mongo_mapper/callbacks.rb +30 -78
  10. data/lib/mongo_mapper/dirty.rb +5 -24
  11. data/lib/mongo_mapper/document.rb +117 -144
  12. data/lib/mongo_mapper/embedded_document.rb +7 -11
  13. data/lib/mongo_mapper/finder_options.rb +13 -21
  14. data/lib/mongo_mapper/mongo_mapper.rb +125 -0
  15. data/lib/mongo_mapper/pagination.rb +12 -1
  16. data/lib/mongo_mapper/rails_compatibility/embedded_document.rb +1 -0
  17. data/lib/mongo_mapper/serialization.rb +2 -2
  18. data/lib/mongo_mapper/serializers/json_serializer.rb +2 -46
  19. data/lib/mongo_mapper/support.rb +2 -2
  20. data/lib/mongo_mapper.rb +8 -2
  21. data/mongo_mapper.gemspec +14 -8
  22. data/specs.watchr +3 -5
  23. data/test/functional/associations/test_belongs_to_polymorphic_proxy.rb +8 -0
  24. data/test/functional/associations/test_belongs_to_proxy.rb +54 -9
  25. data/test/functional/associations/test_in_array_proxy.rb +309 -0
  26. data/test/functional/associations/test_many_documents_proxy.rb +103 -53
  27. data/test/functional/associations/test_many_embedded_proxy.rb +4 -14
  28. data/test/functional/associations/test_many_polymorphic_proxy.rb +2 -1
  29. data/test/functional/associations/test_one_proxy.rb +149 -0
  30. data/test/functional/test_binary.rb +13 -4
  31. data/test/functional/test_callbacks.rb +1 -5
  32. data/test/functional/test_dirty.rb +1 -4
  33. data/test/functional/test_document.rb +576 -640
  34. data/test/functional/test_embedded_document.rb +7 -20
  35. data/test/functional/test_modifiers.rb +238 -0
  36. data/test/functional/test_pagination.rb +1 -3
  37. data/test/functional/test_string_id_compatibility.rb +3 -8
  38. data/test/functional/test_validations.rb +13 -75
  39. data/test/models.rb +1 -1
  40. data/test/support/timing.rb +1 -1
  41. data/test/test_helper.rb +28 -0
  42. data/test/unit/associations/test_base.rb +54 -13
  43. data/test/unit/associations/test_proxy.rb +12 -0
  44. data/test/unit/test_document.rb +36 -26
  45. data/test/unit/test_embedded_document.rb +14 -51
  46. data/test/unit/test_finder_options.rb +20 -7
  47. data/test/unit/test_key.rb +1 -4
  48. data/test/unit/test_pagination.rb +6 -0
  49. data/test/unit/test_rails_compatibility.rb +4 -1
  50. data/test/unit/test_serializations.rb +1 -2
  51. data/test/unit/test_support.rb +4 -0
  52. data/test/unit/test_time_zones.rb +1 -2
  53. data/test/unit/test_validations.rb +3 -14
  54. metadata +12 -6
  55. data/lib/mongo_mapper/observing.rb +0 -50
  56. data/test/unit/test_observing.rb +0 -101
@@ -10,6 +10,7 @@ module MongoMapper
10
10
 
11
11
  class << model
12
12
  alias has_many many
13
+ alias has_one one
13
14
  end
14
15
  end
15
16
 
@@ -1,8 +1,8 @@
1
1
  require 'active_support/json'
2
2
 
3
- module MongoMapper #:nodoc:
3
+ module MongoMapper
4
4
  module Serialization
5
- class Serializer #:nodoc:
5
+ class Serializer
6
6
  attr_reader :options
7
7
 
8
8
  def initialize(record, options={})
@@ -1,54 +1,10 @@
1
- module MongoMapper #:nodoc:
1
+ module MongoMapper
2
2
  module Serialization
3
3
  def self.included(base)
4
4
  base.cattr_accessor :include_root_in_json, :instance_writer => false
5
5
  base.extend ClassMethods
6
6
  end
7
7
 
8
- # Returns a JSON string representing the model. Some configuration is
9
- # available through +options+.
10
- #
11
- # The option <tt>include_root_in_json</tt> controls the top-level behavior of
12
- # to_json. When it is <tt>true</tt>, to_json will emit a single root node named
13
- # after the object's type. For example:
14
- #
15
- # konata = User.find(1)
16
- # User.include_root_in_json = true
17
- # konata.to_json
18
- # # => { "user": {"id": 1, "name": "Konata Izumi", "age": 16,
19
- # "created_at": "2006/08/01", "awesome": true} }
20
- #
21
- # User.include_root_in_json = false
22
- # konata.to_json
23
- # # => {"id": 1, "name": "Konata Izumi", "age": 16,
24
- # "created_at": "2006/08/01", "awesome": true}
25
- #
26
- # The remainder of the examples in this section assume include_root_in_json is set to
27
- # <tt>false</tt>.
28
- #
29
- # Without any +options+, the returned JSON string will include all
30
- # the model's attributes. For example:
31
- #
32
- # konata = User.find(1)
33
- # konata.to_json
34
- # # => {"id": 1, "name": "Konata Izumi", "age": 16,
35
- # "created_at": "2006/08/01", "awesome": true}
36
- #
37
- # The <tt>:only</tt> and <tt>:except</tt> options can be used to limit the attributes
38
- # included, and work similar to the +attributes+ method. For example:
39
- #
40
- # konata.to_json(:only => [ :id, :name ])
41
- # # => {"id": 1, "name": "Konata Izumi"}
42
- #
43
- # konata.to_json(:except => [ :id, :created_at, :age ])
44
- # # => {"name": "Konata Izumi", "awesome": true}
45
- #
46
- # To include any methods on the model, use <tt>:methods</tt>.
47
- #
48
- # konata.to_json(:methods => :permalink)
49
- # # => {"id": 1, "name": "Konata Izumi", "age": 16,
50
- # "created_at": "2006/08/01", "awesome": true,
51
- # "permalink": "1-konata-izumi"}
52
8
  def to_json(options={})
53
9
  apply_to_json_defaults(options)
54
10
 
@@ -64,7 +20,7 @@ module MongoMapper #:nodoc:
64
20
  self
65
21
  end
66
22
 
67
- class JsonSerializer < MongoMapper::Serialization::Serializer #:nodoc:
23
+ class JsonSerializer < MongoMapper::Serialization::Serializer
68
24
  def serialize
69
25
  serializable_record.to_json
70
26
  end
@@ -120,7 +120,7 @@ end
120
120
 
121
121
  class ObjectId
122
122
  def self.to_mongo(value)
123
- if value.nil?
123
+ if value.blank?
124
124
  nil
125
125
  elsif value.is_a?(Mongo::ObjectID)
126
126
  value
@@ -165,7 +165,7 @@ class Symbol
165
165
  def desc; MongoMapper::OrderOperator.new(self, 'desc') end
166
166
  end
167
167
 
168
- class Time
168
+ class Time
169
169
  def self.to_mongo(value)
170
170
  if value.nil? || value == ''
171
171
  nil
data/lib/mongo_mapper.rb CHANGED
@@ -4,7 +4,7 @@
4
4
  # if there is a better way to do this, please enlighten me!
5
5
  if self.class.const_defined?(:Gem)
6
6
  gem 'activesupport', '>= 2.3'
7
- gem 'mongo', '0.18.1'
7
+ gem 'mongo', '0.18.2'
8
8
  gem 'jnunemaker-validatable', '1.8.1'
9
9
  end
10
10
 
@@ -64,6 +64,11 @@ module MongoMapper
64
64
  @@ensured_indexes ||= []
65
65
  end
66
66
 
67
+ # @api private
68
+ def self.ensured_indexes=(value)
69
+ @@ensured_indexes = value
70
+ end
71
+
67
72
  # @api private
68
73
  def self.ensure_index(klass, keys, options={})
69
74
  ensured_indexes << {:klass => klass, :keys => keys, :options => options}
@@ -99,7 +104,6 @@ require 'mongo_mapper/finder_options'
99
104
  require 'mongo_mapper/dirty'
100
105
  require 'mongo_mapper/dynamic_finder'
101
106
  require 'mongo_mapper/key'
102
- require 'mongo_mapper/observing'
103
107
  require 'mongo_mapper/pagination'
104
108
  require 'mongo_mapper/serialization'
105
109
  require 'mongo_mapper/validations'
@@ -118,3 +122,5 @@ require 'mongo_mapper/associations/many_polymorphic_proxy'
118
122
  require 'mongo_mapper/associations/many_embedded_proxy'
119
123
  require 'mongo_mapper/associations/many_embedded_polymorphic_proxy'
120
124
  require 'mongo_mapper/associations/many_documents_as_proxy'
125
+ require 'mongo_mapper/associations/one_proxy'
126
+ require 'mongo_mapper/associations/in_array_proxy'
data/mongo_mapper.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{mongo_mapper}
8
- s.version = "0.6.8"
8
+ s.version = "0.6.10"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["John Nunemaker"]
12
- s.date = %q{2009-12-15}
12
+ s.date = %q{2010-01-02}
13
13
  s.default_executable = %q{mmconsole}
14
14
  s.email = %q{nunemaker@gmail.com}
15
15
  s.executables = ["mmconsole"]
@@ -30,11 +30,13 @@ Gem::Specification.new do |s|
30
30
  "lib/mongo_mapper/associations/belongs_to_polymorphic_proxy.rb",
31
31
  "lib/mongo_mapper/associations/belongs_to_proxy.rb",
32
32
  "lib/mongo_mapper/associations/collection.rb",
33
+ "lib/mongo_mapper/associations/in_array_proxy.rb",
33
34
  "lib/mongo_mapper/associations/many_documents_as_proxy.rb",
34
35
  "lib/mongo_mapper/associations/many_documents_proxy.rb",
35
36
  "lib/mongo_mapper/associations/many_embedded_polymorphic_proxy.rb",
36
37
  "lib/mongo_mapper/associations/many_embedded_proxy.rb",
37
38
  "lib/mongo_mapper/associations/many_polymorphic_proxy.rb",
39
+ "lib/mongo_mapper/associations/one_proxy.rb",
38
40
  "lib/mongo_mapper/associations/proxy.rb",
39
41
  "lib/mongo_mapper/callbacks.rb",
40
42
  "lib/mongo_mapper/dirty.rb",
@@ -43,7 +45,7 @@ Gem::Specification.new do |s|
43
45
  "lib/mongo_mapper/embedded_document.rb",
44
46
  "lib/mongo_mapper/finder_options.rb",
45
47
  "lib/mongo_mapper/key.rb",
46
- "lib/mongo_mapper/observing.rb",
48
+ "lib/mongo_mapper/mongo_mapper.rb",
47
49
  "lib/mongo_mapper/pagination.rb",
48
50
  "lib/mongo_mapper/rails_compatibility/document.rb",
49
51
  "lib/mongo_mapper/rails_compatibility/embedded_document.rb",
@@ -56,11 +58,13 @@ Gem::Specification.new do |s|
56
58
  "test/NOTE_ON_TESTING",
57
59
  "test/functional/associations/test_belongs_to_polymorphic_proxy.rb",
58
60
  "test/functional/associations/test_belongs_to_proxy.rb",
61
+ "test/functional/associations/test_in_array_proxy.rb",
59
62
  "test/functional/associations/test_many_documents_as_proxy.rb",
60
63
  "test/functional/associations/test_many_documents_proxy.rb",
61
64
  "test/functional/associations/test_many_embedded_polymorphic_proxy.rb",
62
65
  "test/functional/associations/test_many_embedded_proxy.rb",
63
66
  "test/functional/associations/test_many_polymorphic_proxy.rb",
67
+ "test/functional/associations/test_one_proxy.rb",
64
68
  "test/functional/test_associations.rb",
65
69
  "test/functional/test_binary.rb",
66
70
  "test/functional/test_callbacks.rb",
@@ -68,6 +72,7 @@ Gem::Specification.new do |s|
68
72
  "test/functional/test_document.rb",
69
73
  "test/functional/test_embedded_document.rb",
70
74
  "test/functional/test_logger.rb",
75
+ "test/functional/test_modifiers.rb",
71
76
  "test/functional/test_pagination.rb",
72
77
  "test/functional/test_rails_compatibility.rb",
73
78
  "test/functional/test_string_id_compatibility.rb",
@@ -85,7 +90,6 @@ Gem::Specification.new do |s|
85
90
  "test/unit/test_finder_options.rb",
86
91
  "test/unit/test_key.rb",
87
92
  "test/unit/test_mongo_mapper.rb",
88
- "test/unit/test_observing.rb",
89
93
  "test/unit/test_pagination.rb",
90
94
  "test/unit/test_rails_compatibility.rb",
91
95
  "test/unit/test_serializations.rb",
@@ -101,11 +105,13 @@ Gem::Specification.new do |s|
101
105
  s.test_files = [
102
106
  "test/functional/associations/test_belongs_to_polymorphic_proxy.rb",
103
107
  "test/functional/associations/test_belongs_to_proxy.rb",
108
+ "test/functional/associations/test_in_array_proxy.rb",
104
109
  "test/functional/associations/test_many_documents_as_proxy.rb",
105
110
  "test/functional/associations/test_many_documents_proxy.rb",
106
111
  "test/functional/associations/test_many_embedded_polymorphic_proxy.rb",
107
112
  "test/functional/associations/test_many_embedded_proxy.rb",
108
113
  "test/functional/associations/test_many_polymorphic_proxy.rb",
114
+ "test/functional/associations/test_one_proxy.rb",
109
115
  "test/functional/test_associations.rb",
110
116
  "test/functional/test_binary.rb",
111
117
  "test/functional/test_callbacks.rb",
@@ -113,6 +119,7 @@ Gem::Specification.new do |s|
113
119
  "test/functional/test_document.rb",
114
120
  "test/functional/test_embedded_document.rb",
115
121
  "test/functional/test_logger.rb",
122
+ "test/functional/test_modifiers.rb",
116
123
  "test/functional/test_pagination.rb",
117
124
  "test/functional/test_rails_compatibility.rb",
118
125
  "test/functional/test_string_id_compatibility.rb",
@@ -130,7 +137,6 @@ Gem::Specification.new do |s|
130
137
  "test/unit/test_finder_options.rb",
131
138
  "test/unit/test_key.rb",
132
139
  "test/unit/test_mongo_mapper.rb",
133
- "test/unit/test_observing.rb",
134
140
  "test/unit/test_pagination.rb",
135
141
  "test/unit/test_rails_compatibility.rb",
136
142
  "test/unit/test_serializations.rb",
@@ -145,7 +151,7 @@ Gem::Specification.new do |s|
145
151
 
146
152
  if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
147
153
  s.add_runtime_dependency(%q<activesupport>, [">= 2.3"])
148
- s.add_runtime_dependency(%q<mongo>, ["= 0.18.1"])
154
+ s.add_runtime_dependency(%q<mongo>, ["= 0.18.2"])
149
155
  s.add_runtime_dependency(%q<jnunemaker-validatable>, ["= 1.8.1"])
150
156
  s.add_development_dependency(%q<jnunemaker-matchy>, ["= 0.4.0"])
151
157
  s.add_development_dependency(%q<shoulda>, ["= 2.10.2"])
@@ -153,7 +159,7 @@ Gem::Specification.new do |s|
153
159
  s.add_development_dependency(%q<mocha>, ["= 0.9.8"])
154
160
  else
155
161
  s.add_dependency(%q<activesupport>, [">= 2.3"])
156
- s.add_dependency(%q<mongo>, ["= 0.18.1"])
162
+ s.add_dependency(%q<mongo>, ["= 0.18.2"])
157
163
  s.add_dependency(%q<jnunemaker-validatable>, ["= 1.8.1"])
158
164
  s.add_dependency(%q<jnunemaker-matchy>, ["= 0.4.0"])
159
165
  s.add_dependency(%q<shoulda>, ["= 2.10.2"])
@@ -162,7 +168,7 @@ Gem::Specification.new do |s|
162
168
  end
163
169
  else
164
170
  s.add_dependency(%q<activesupport>, [">= 2.3"])
165
- s.add_dependency(%q<mongo>, ["= 0.18.1"])
171
+ s.add_dependency(%q<mongo>, ["= 0.18.2"])
166
172
  s.add_dependency(%q<jnunemaker-validatable>, ["= 1.8.1"])
167
173
  s.add_dependency(%q<jnunemaker-matchy>, ["= 0.4.0"])
168
174
  s.add_dependency(%q<shoulda>, ["= 2.10.2"])
data/specs.watchr CHANGED
@@ -15,11 +15,9 @@ def related_test_files(path)
15
15
  Dir['test/**/*.rb'].select { |file| file =~ /test_#{File.basename(path)}/ }
16
16
  end
17
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
18
+ watch('test/test_helper\.rb') { system('clear'); run_all_tests }
19
+ watch('test/.*/test_.*\.rb') { |m| system('clear'); run_test_file(m[0]) }
20
+ watch('lib/.*') { |m| related_test_files(m[0]).each { |file| system('clear'); run_test_file(file) } }
23
21
 
24
22
  # Ctrl-\
25
23
  Signal.trap('QUIT') do
@@ -12,6 +12,14 @@ class BelongsToPolymorphicProxyTest < Test::Unit::TestCase
12
12
  status.target.nil?.should be_true
13
13
  status.target.inspect.should == "nil"
14
14
  end
15
+
16
+ should "have boolean presence method" do
17
+ status = Status.new
18
+ status.target?.should be_false
19
+
20
+ status.target = Project.new(:name => 'mongomapper')
21
+ status.target?.should be_true
22
+ end
15
23
 
16
24
  should "be able to replace the association" do
17
25
  status = Status.new(:name => 'Foo!')
@@ -3,24 +3,26 @@ require 'models'
3
3
 
4
4
  class BelongsToProxyTest < Test::Unit::TestCase
5
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
6
+ @post_class = Doc()
7
+ @comment_class = Doc do
12
8
  key :post_id, String
13
9
  end
14
- @comment_class.belongs_to :post, :class => @post_class
15
10
 
16
- @post_class.collection.remove
17
- @comment_class.collection.remove
11
+ @comment_class.belongs_to :post, :class => @post_class
18
12
  end
19
13
 
20
14
  should "default to nil" do
21
15
  @comment_class.new.post.nil?.should be_true
22
16
  end
23
17
 
18
+ should "have boolean presence method" do
19
+ comment = @comment_class.new(:name => 'Foo!')
20
+ comment.post?.should be_false
21
+
22
+ comment.post = @post_class.new(:name => 'mongomapper')
23
+ comment.post?.should be_true
24
+ end
25
+
24
26
  should "be able to replace the association" do
25
27
  post = @post_class.new(:name => 'mongomapper')
26
28
  comment = @comment_class.new(:name => 'Foo!', :post => post)
@@ -45,4 +47,47 @@ class BelongsToProxyTest < Test::Unit::TestCase
45
47
  id = Mongo::ObjectID.new
46
48
  @comment_class.new(:name => 'Foo', :post_id => id).post.nil?.should be_true
47
49
  end
50
+
51
+ context ":dependent" do
52
+ setup do
53
+ # FIXME: make use of already defined models
54
+ class ::Property
55
+ include MongoMapper::Document
56
+ end
57
+ Property.collection.remove
58
+
59
+ class ::Thing
60
+ include MongoMapper::Document
61
+ key :name, String
62
+ end
63
+ Thing.collection.remove
64
+ end
65
+
66
+ teardown do
67
+ Object.send :remove_const, 'Property' if defined?(::Property)
68
+ Object.send :remove_const, 'Thing' if defined?(::Thing)
69
+ end
70
+
71
+ context "=> destroy" do
72
+ setup do
73
+ Property.key :thing_id, ObjectId
74
+ Property.belongs_to :thing, :dependent => :destroy
75
+ Thing.has_many :properties
76
+
77
+ @thing = Thing.create(:name => "Tree")
78
+ @property1 = Property.create
79
+ @property2 = Property.create
80
+ @property3 = Property.create
81
+ @thing.properties << @property1
82
+ @thing.properties << @property2
83
+ @thing.properties << @property3
84
+ end
85
+
86
+ should "not execute on a belongs_to association" do
87
+ Thing.count.should == 1
88
+ @property1.destroy
89
+ Thing.count.should == 1
90
+ end
91
+ end
92
+ end
48
93
  end
@@ -0,0 +1,309 @@
1
+ require 'test_helper'
2
+
3
+ class InArrayProxyTest < Test::Unit::TestCase
4
+ context "description" do
5
+ setup do
6
+ class ::List
7
+ include MongoMapper::Document
8
+ key :name, String, :required => true
9
+ end
10
+
11
+ class ::User
12
+ include MongoMapper::Document
13
+ key :name, String, :required => true
14
+ key :list_ids, Array
15
+ many :lists, :in => :list_ids
16
+ end
17
+ User.collection.remove
18
+ List.collection.remove
19
+ end
20
+
21
+ teardown do
22
+ Object.send :remove_const, 'List' if defined?(::List)
23
+ Object.send :remove_const, 'User' if defined?(::User)
24
+ end
25
+
26
+ should "default reader to empty array" do
27
+ User.new.lists.should == []
28
+ end
29
+
30
+ should "allow adding to association like it was an array" do
31
+ user = User.new(:name => 'John')
32
+ user.lists << List.new(:name => 'Foo1!')
33
+ user.lists.push List.new(:name => 'Foo2!')
34
+ user.lists.concat List.new(:name => 'Foo3!')
35
+ user.lists.size.should == 3
36
+ end
37
+
38
+ should "ignore adding duplicate ids" do
39
+ user = User.create(:name => 'John')
40
+ list = List.create(:name => 'Foo')
41
+ user.lists << list
42
+ user.lists << list
43
+ user.lists << list
44
+
45
+ user.list_ids.should == [list.id]
46
+ user.lists.count.should == 1
47
+ end
48
+
49
+ should "be able to replace the association" do
50
+ user = User.new(:name => 'John')
51
+ list = List.new(:name => 'Foo')
52
+ user.lists = [list]
53
+ user.save.should be_true
54
+
55
+ user.reload
56
+ user.list_ids.should == [list.id]
57
+ user.lists.size.should == 1
58
+ user.lists[0].name.should == 'Foo'
59
+ end
60
+
61
+ context "create" do
62
+ setup do
63
+ @user = User.create(:name => 'John')
64
+ @list = @user.lists.create(:name => 'Foo!')
65
+ end
66
+
67
+ should "add id to key" do
68
+ @user.list_ids.should include(@list.id)
69
+ end
70
+
71
+ should "persist id addition to key in database" do
72
+ @user.reload
73
+ @user.list_ids.should include(@list.id)
74
+ end
75
+
76
+ should "add doc to association" do
77
+ @user.lists.should include(@list)
78
+ end
79
+
80
+ should "save doc" do
81
+ @list.should_not be_new
82
+ end
83
+ end
84
+
85
+ context "create!" do
86
+ setup do
87
+ @user = User.create(:name => 'John')
88
+ @list = @user.lists.create!(:name => 'Foo!')
89
+ end
90
+
91
+ should "add id to key" do
92
+ @user.list_ids.should include(@list.id)
93
+ end
94
+
95
+ should "persist id addition to key in database" do
96
+ @user.reload
97
+ @user.list_ids.should include(@list.id)
98
+ end
99
+
100
+ should "add doc to association" do
101
+ @user.lists.should include(@list)
102
+ end
103
+
104
+ should "save doc" do
105
+ @list.should_not be_new
106
+ end
107
+
108
+ should "raise exception if invalid" do
109
+ assert_raises(MongoMapper::DocumentNotValid) do
110
+ @user.lists.create!
111
+ end
112
+ end
113
+ end
114
+
115
+ context "Finding scoped to association" do
116
+ setup do
117
+ @user = User.create(:name => 'John')
118
+ @user2 = User.create(:name => 'Brandon')
119
+ @list1 = @user.lists.create!(:name => 'Foo 1', :position => 1)
120
+ @list2 = @user.lists.create!(:name => 'Foo 2', :position => 2)
121
+ @list3 = @user2.lists.create!(:name => 'Foo 3', :position => 1)
122
+ end
123
+
124
+ context "all" do
125
+ should "work" do
126
+ @user.lists.find(:all, :order => :position.asc).should == [@list1, @list2]
127
+ @user.lists.all(:order => :position.asc).should == [@list1, @list2]
128
+ end
129
+
130
+ should "work with conditions" do
131
+ @user.lists.find(:all, :name => 'Foo 1').should == [@list1]
132
+ @user.lists.all(:name => 'Foo 1').should == [@list1]
133
+ end
134
+ end
135
+
136
+ context "first" do
137
+ should "work" do
138
+ @user.lists.find(:first, :order => 'position').should == @list1
139
+ @user.lists.first(:order => 'position').should == @list1
140
+ end
141
+
142
+ should "work with conditions" do
143
+ @user.lists.find(:first, :position => 2).should == @list2
144
+ @user.lists.first(:position => 2).should == @list2
145
+ end
146
+ end
147
+
148
+ context "last" do
149
+ should "work" do
150
+ @user.lists.find(:last, :order => 'position').should == @list2
151
+ @user.lists.last(:order => 'position').should == @list2
152
+ end
153
+
154
+ should "work with conditions" do
155
+ @user.lists.find(:last, :position => 2, :order => 'position').should == @list2
156
+ @user.lists.last(:position => 2, :order => 'position').should == @list2
157
+ end
158
+ end
159
+
160
+ context "with one id" do
161
+ should "work for id in association" do
162
+ @user.lists.find(@list1.id).should == @list1
163
+ end
164
+
165
+ should "not work for id not in association" do
166
+ @user.lists.find(@list3.id).should be_nil
167
+ end
168
+
169
+ should "raise error when using ! and not found" do
170
+ assert_raises MongoMapper::DocumentNotFound do
171
+ @user.lists.find!(@list3.id)
172
+ end
173
+ end
174
+ end
175
+
176
+ context "with multiple ids" do
177
+ should "work for ids in association" do
178
+ @user.lists.find(@list1.id, @list2.id).should == [@list1, @list2]
179
+ end
180
+
181
+ should "not work for ids not in association" do
182
+ @user.lists.find(@list1.id, @list2.id, @list3.id).should == [@list1, @list2]
183
+ end
184
+ end
185
+
186
+ context "with #paginate" do
187
+ setup do
188
+ @lists = @user.lists.paginate(:per_page => 1, :page => 1, :order => 'position')
189
+ end
190
+
191
+ should "return total pages" do
192
+ @lists.total_pages.should == 2
193
+ end
194
+
195
+ should "return total entries" do
196
+ @lists.total_entries.should == 2
197
+ end
198
+
199
+ should "return the subject" do
200
+ @lists.collect(&:name).should == ['Foo 1']
201
+ end
202
+ end
203
+
204
+ context "dynamic finders" do
205
+ should "work with single key" do
206
+ @user.lists.find_by_name('Foo 1').should == @list1
207
+ @user.lists.find_by_name!('Foo 1').should == @list1
208
+ @user.lists.find_by_name('Foo 3').should be_nil
209
+ end
210
+
211
+ should "work with multiple keys" do
212
+ @user.lists.find_by_name_and_position('Foo 1', 1).should == @list1
213
+ @user.lists.find_by_name_and_position!('Foo 1', 1).should == @list1
214
+ @user.lists.find_by_name_and_position('Foo 3', 1).should be_nil
215
+ end
216
+
217
+ should "raise error when using ! and not found" do
218
+ assert_raises(MongoMapper::DocumentNotFound) do
219
+ @user.lists.find_by_name!('Foo 3')
220
+ end
221
+ end
222
+
223
+ context "find_or_create_by" do
224
+ should "not create document if found" do
225
+ lambda {
226
+ list = @user.lists.find_or_create_by_name('Foo 1')
227
+ list.should == @list1
228
+ }.should_not change { List.count }
229
+ end
230
+
231
+ should "create document if not found" do
232
+ lambda {
233
+ list = @user.lists.find_or_create_by_name('Home')
234
+ @user.lists.should include(list)
235
+ }.should change { List.count }
236
+ end
237
+ end
238
+ end
239
+ end
240
+
241
+ context "count" do
242
+ setup do
243
+ @user = User.create(:name => 'John')
244
+ @user2 = User.create(:name => 'Brandon')
245
+ @list1 = @user.lists.create!(:name => 'Foo 1')
246
+ @list2 = @user.lists.create!(:name => 'Foo 2')
247
+ @list3 = @user2.lists.create!(:name => 'Foo 3')
248
+ end
249
+
250
+ should "return number of ids" do
251
+ @user.lists.count.should == 2
252
+ @user2.lists.count.should == 1
253
+ end
254
+
255
+ should "return correct count when given criteria" do
256
+ @user.lists.count(:name => 'Foo 1').should == 1
257
+ @user2.lists.count(:name => 'Foo 1').should == 0
258
+ end
259
+ end
260
+
261
+ context "Removing documents" do
262
+ setup do
263
+ @user = User.create(:name => 'John')
264
+ @user2 = User.create(:name => 'Brandon')
265
+ @list1 = @user.lists.create!(:name => 'Foo 1', :position => 1)
266
+ @list2 = @user.lists.create!(:name => 'Foo 2', :position => 2)
267
+ @list3 = @user2.lists.create!(:name => 'Foo 3', :position => 1)
268
+ end
269
+
270
+ context "destroy_all" do
271
+ should "work" do
272
+ @user.lists.count.should == 2
273
+ @user.lists.destroy_all
274
+ @user.lists.count.should == 0
275
+ end
276
+
277
+ should "work with conditions" do
278
+ @user.lists.count.should == 2
279
+ @user.lists.destroy_all(:name => 'Foo 1')
280
+ @user.lists.count.should == 1
281
+ end
282
+ end
283
+
284
+ context "delete_all" do
285
+ should "work" do
286
+ @user.lists.count.should == 2
287
+ @user.lists.delete_all
288
+ @user.lists.count.should == 0
289
+ end
290
+
291
+ should "work with conditions" do
292
+ @user.lists.count.should == 2
293
+ @user.lists.delete_all(:name => 'Foo 1')
294
+ @user.lists.count.should == 1
295
+ end
296
+ end
297
+
298
+ should "work with nullify" do
299
+ @user.lists.count.should == 2
300
+
301
+ lambda {
302
+ @user.lists.nullify
303
+ }.should_not change { List.count }
304
+
305
+ @user.lists.count.should == 0
306
+ end
307
+ end
308
+ end
309
+ end