mongo_mapper 0.6.10 → 0.7.0

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 (106) hide show
  1. data/README.rdoc +5 -14
  2. data/Rakefile +1 -1
  3. data/VERSION +1 -1
  4. data/lib/mongo_mapper.rb +48 -56
  5. data/lib/mongo_mapper/document.rb +136 -164
  6. data/lib/mongo_mapper/embedded_document.rb +29 -354
  7. data/lib/mongo_mapper/plugins.rb +31 -0
  8. data/lib/mongo_mapper/plugins/associations.rb +105 -0
  9. data/lib/mongo_mapper/plugins/associations/base.rb +123 -0
  10. data/lib/mongo_mapper/plugins/associations/belongs_to_polymorphic_proxy.rb +30 -0
  11. data/lib/mongo_mapper/plugins/associations/belongs_to_proxy.rb +25 -0
  12. data/lib/mongo_mapper/plugins/associations/collection.rb +21 -0
  13. data/lib/mongo_mapper/plugins/associations/embedded_collection.rb +50 -0
  14. data/lib/mongo_mapper/plugins/associations/in_array_proxy.rb +139 -0
  15. data/lib/mongo_mapper/plugins/associations/many_documents_as_proxy.rb +28 -0
  16. data/lib/mongo_mapper/plugins/associations/many_documents_proxy.rb +117 -0
  17. data/lib/mongo_mapper/plugins/associations/many_embedded_polymorphic_proxy.rb +31 -0
  18. data/lib/mongo_mapper/plugins/associations/many_embedded_proxy.rb +23 -0
  19. data/lib/mongo_mapper/plugins/associations/many_polymorphic_proxy.rb +13 -0
  20. data/lib/mongo_mapper/plugins/associations/one_proxy.rb +68 -0
  21. data/lib/mongo_mapper/plugins/associations/proxy.rb +118 -0
  22. data/lib/mongo_mapper/plugins/callbacks.rb +65 -0
  23. data/lib/mongo_mapper/plugins/clone.rb +13 -0
  24. data/lib/mongo_mapper/plugins/descendants.rb +16 -0
  25. data/lib/mongo_mapper/plugins/dirty.rb +119 -0
  26. data/lib/mongo_mapper/plugins/equality.rb +23 -0
  27. data/lib/mongo_mapper/plugins/identity_map.rb +122 -0
  28. data/lib/mongo_mapper/plugins/inspect.rb +14 -0
  29. data/lib/mongo_mapper/plugins/keys.rb +324 -0
  30. data/lib/mongo_mapper/plugins/logger.rb +17 -0
  31. data/lib/mongo_mapper/plugins/pagination.rb +24 -0
  32. data/lib/mongo_mapper/plugins/pagination/proxy.rb +68 -0
  33. data/lib/mongo_mapper/plugins/protected.rb +45 -0
  34. data/lib/mongo_mapper/plugins/rails.rb +45 -0
  35. data/lib/mongo_mapper/plugins/serialization.rb +105 -0
  36. data/lib/mongo_mapper/plugins/validations.rb +46 -0
  37. data/lib/mongo_mapper/query.rb +130 -0
  38. data/lib/mongo_mapper/support.rb +40 -17
  39. data/lib/mongo_mapper/support/descendant_appends.rb +46 -0
  40. data/lib/mongo_mapper/support/find.rb +77 -0
  41. data/mongo_mapper.gemspec +55 -38
  42. data/performance/read_write.rb +52 -0
  43. data/specs.watchr +23 -2
  44. data/test/functional/associations/test_belongs_to_proxy.rb +12 -10
  45. data/test/functional/associations/test_many_documents_as_proxy.rb +4 -21
  46. data/test/functional/associations/test_many_documents_proxy.rb +2 -8
  47. data/test/functional/associations/test_many_embedded_polymorphic_proxy.rb +59 -39
  48. data/test/functional/associations/test_many_embedded_proxy.rb +145 -81
  49. data/test/functional/associations/test_many_polymorphic_proxy.rb +2 -40
  50. data/test/functional/associations/test_one_proxy.rb +25 -10
  51. data/test/functional/test_binary.rb +2 -8
  52. data/test/functional/test_callbacks.rb +1 -5
  53. data/test/functional/test_dirty.rb +27 -23
  54. data/test/functional/test_document.rb +224 -165
  55. data/test/functional/test_embedded_document.rb +72 -82
  56. data/test/functional/test_identity_map.rb +508 -0
  57. data/test/functional/test_modifiers.rb +15 -5
  58. data/test/functional/test_pagination.rb +1 -3
  59. data/test/functional/test_protected.rb +155 -0
  60. data/test/functional/test_string_id_compatibility.rb +7 -12
  61. data/test/functional/test_validations.rb +26 -58
  62. data/test/models.rb +0 -39
  63. data/test/test_helper.rb +37 -3
  64. data/test/unit/associations/test_base.rb +5 -5
  65. data/test/unit/associations/test_proxy.rb +8 -6
  66. data/test/unit/test_descendant_appends.rb +71 -0
  67. data/test/unit/test_document.rb +71 -76
  68. data/test/unit/test_dynamic_finder.rb +27 -29
  69. data/test/unit/test_embedded_document.rb +555 -601
  70. data/test/unit/{test_key.rb → test_keys.rb} +2 -5
  71. data/test/unit/test_mongo_mapper.rb +69 -9
  72. data/test/unit/test_pagination.rb +40 -32
  73. data/test/unit/test_plugins.rb +50 -0
  74. data/test/unit/{test_finder_options.rb → test_query.rb} +74 -65
  75. data/test/unit/test_rails.rb +123 -0
  76. data/test/unit/{test_serializations.rb → test_serialization.rb} +1 -2
  77. data/test/unit/test_support.rb +23 -7
  78. data/test/unit/test_time_zones.rb +3 -4
  79. data/test/unit/test_validations.rb +58 -17
  80. metadata +53 -36
  81. data/lib/mongo_mapper/associations.rb +0 -78
  82. data/lib/mongo_mapper/associations/base.rb +0 -119
  83. data/lib/mongo_mapper/associations/belongs_to_polymorphic_proxy.rb +0 -26
  84. data/lib/mongo_mapper/associations/belongs_to_proxy.rb +0 -21
  85. data/lib/mongo_mapper/associations/collection.rb +0 -19
  86. data/lib/mongo_mapper/associations/in_array_proxy.rb +0 -137
  87. data/lib/mongo_mapper/associations/many_documents_as_proxy.rb +0 -26
  88. data/lib/mongo_mapper/associations/many_documents_proxy.rb +0 -115
  89. data/lib/mongo_mapper/associations/many_embedded_polymorphic_proxy.rb +0 -31
  90. data/lib/mongo_mapper/associations/many_embedded_proxy.rb +0 -54
  91. data/lib/mongo_mapper/associations/many_polymorphic_proxy.rb +0 -11
  92. data/lib/mongo_mapper/associations/one_proxy.rb +0 -64
  93. data/lib/mongo_mapper/associations/proxy.rb +0 -116
  94. data/lib/mongo_mapper/callbacks.rb +0 -61
  95. data/lib/mongo_mapper/dirty.rb +0 -117
  96. data/lib/mongo_mapper/dynamic_finder.rb +0 -74
  97. data/lib/mongo_mapper/finder_options.rb +0 -145
  98. data/lib/mongo_mapper/key.rb +0 -36
  99. data/lib/mongo_mapper/mongo_mapper.rb +0 -125
  100. data/lib/mongo_mapper/pagination.rb +0 -66
  101. data/lib/mongo_mapper/rails_compatibility/document.rb +0 -15
  102. data/lib/mongo_mapper/rails_compatibility/embedded_document.rb +0 -28
  103. data/lib/mongo_mapper/serialization.rb +0 -54
  104. data/lib/mongo_mapper/serializers/json_serializer.rb +0 -48
  105. data/lib/mongo_mapper/validations.rb +0 -39
  106. data/test/functional/test_rails_compatibility.rb +0 -25
@@ -109,12 +109,6 @@ class Answer
109
109
  key :body, String
110
110
  end
111
111
 
112
- module PeopleExtensions
113
- def find_by_name(name)
114
- detect { |p| p.name == name }
115
- end
116
- end
117
-
118
112
  module CollaboratorsExtensions
119
113
  def top
120
114
  first
@@ -126,9 +120,7 @@ class Project
126
120
 
127
121
  key :name, String
128
122
 
129
- many :people, :extend => PeopleExtensions
130
123
  many :collaborators, :extend => CollaboratorsExtensions
131
-
132
124
  many :statuses, :order => 'position' do
133
125
  def open
134
126
  all(:name => %w(New Assigned))
@@ -163,37 +155,6 @@ class Status
163
155
  belongs_to :target, :polymorphic => true
164
156
  end
165
157
 
166
- class RealPerson
167
- include MongoMapper::Document
168
-
169
- key :room_id, ObjectId
170
- key :name, String
171
-
172
- belongs_to :room
173
-
174
- many :pets
175
-
176
- def realname=(n)
177
- self.name = n
178
- end
179
- end
180
-
181
- class Person
182
- include MongoMapper::EmbeddedDocument
183
-
184
- key :name, String
185
- key :child, Person
186
-
187
- many :pets
188
- end
189
-
190
- class Pet
191
- include MongoMapper::EmbeddedDocument
192
-
193
- key :name, String
194
- key :species, String
195
- end
196
-
197
158
  class Media
198
159
  include MongoMapper::EmbeddedDocument
199
160
 
@@ -16,12 +16,46 @@ require 'support/timing'
16
16
 
17
17
  class Test::Unit::TestCase
18
18
  include CustomMatchers
19
+
20
+ def Doc(name=nil, &block)
21
+ klass = Class.new do
22
+ include MongoMapper::Document
23
+ set_collection_name "test#{rand(20)}"
24
+
25
+ if name
26
+ class_eval "def self.name; '#{name}' end"
27
+ class_eval "def self.to_s; '#{name}' end"
28
+ end
29
+ end
30
+
31
+ klass.class_eval(&block) if block_given?
32
+ klass.collection.remove
33
+ klass
34
+ end
35
+
36
+ def EDoc(name=nil, &block)
37
+ klass = Class.new do
38
+ include MongoMapper::EmbeddedDocument
39
+
40
+ if name
41
+ class_eval "def self.name; '#{name}' end"
42
+ class_eval "def self.to_s; '#{name}' end"
43
+ end
44
+ end
45
+
46
+ klass.class_eval(&block) if block_given?
47
+ klass
48
+ end
49
+
50
+ def drop_indexes(klass)
51
+ if klass.database.collection_names.include?(klass.collection.name)
52
+ klass.collection.drop_indexes
53
+ end
54
+ end
19
55
  end
20
56
 
21
57
  test_dir = File.expand_path(File.dirname(__FILE__) + '/../tmp')
22
58
  FileUtils.mkdir_p(test_dir) unless File.exist?(test_dir)
23
59
 
24
- MongoMapper.connection = Mongo::Connection.new('127.0.0.1', 27017, {
25
- :logger => Logger.new(test_dir + '/test.log')
26
- })
60
+ MongoMapper.connection = Mongo::Connection.new('127.0.0.1', 27017, {:logger => Logger.new(test_dir + '/test.log')})
27
61
  MongoMapper.database = 'test'
@@ -4,7 +4,7 @@ require 'models'
4
4
  class FooMonster; end
5
5
 
6
6
  class AssociationBaseTest < Test::Unit::TestCase
7
- include MongoMapper::Associations
7
+ include MongoMapper::Plugins::Associations
8
8
 
9
9
  should "initialize with type and name" do
10
10
  base = Base.new(:many, :foos)
@@ -104,20 +104,20 @@ class AssociationBaseTest < Test::Unit::TestCase
104
104
  end
105
105
  end
106
106
 
107
- context "finder_options" do
107
+ context "query_options" do
108
108
  should "default to empty hash" do
109
109
  base = Base.new(:many, :foos)
110
- base.finder_options.should == {}
110
+ base.query_options.should == {}
111
111
  end
112
112
 
113
113
  should "work with order" do
114
114
  base = Base.new(:many, :foos, :order => 'position')
115
- base.finder_options.should == {:order => 'position'}
115
+ base.query_options.should == {:order => 'position'}
116
116
  end
117
117
 
118
118
  should "correctly parse from options" do
119
119
  base = Base.new(:many, :foos, :order => 'position', :somekey => 'somevalue')
120
- base.finder_options.should == {:order => 'position', :somekey => 'somevalue'}
120
+ base.query_options.should == {:order => 'position', :somekey => 'somevalue'}
121
121
  end
122
122
  end
123
123
 
@@ -1,17 +1,19 @@
1
1
  require 'test_helper'
2
2
 
3
- class FakeNilProxy < MongoMapper::Associations::Proxy
3
+ class FakeNilProxy < MongoMapper::Plugins::Associations::Proxy
4
4
  def find_target; nil end
5
5
  end
6
6
 
7
- class FakeBlankProxy < MongoMapper::Associations::Proxy
7
+ class FakeBlankProxy < MongoMapper::Plugins::Associations::Proxy
8
8
  def find_target; '' end
9
9
  end
10
10
 
11
- class FakeProxy < MongoMapper::Associations::Proxy
12
- def find_target
13
- [1, 2]
14
- end
11
+ class FakeNumberProxy < MongoMapper::Plugins::Associations::Proxy
12
+ def find_target; 17 end
13
+ end
14
+
15
+ class FakeProxy < MongoMapper::Plugins::Associations::Proxy
16
+ def find_target; [1, 2] end
15
17
  end
16
18
 
17
19
  class ProxyTest < Test::Unit::TestCase
@@ -0,0 +1,71 @@
1
+ require 'test_helper'
2
+
3
+ class DescendantAppendsTest < Test::Unit::TestCase
4
+ context "Document" do
5
+ should "default descendants to a new set" do
6
+ MongoMapper::Document.descendants.should be_instance_of(Set)
7
+ end
8
+
9
+ should 'allow extensions to Document to be appended' do
10
+ module Extension; def test_this_extension; end end
11
+ MongoMapper::Document.append_extensions(Extension)
12
+ article = Doc()
13
+ article.should respond_to(:test_this_extension)
14
+ end
15
+
16
+ should 'add appended extensions to classes that include Document before they are added' do
17
+ module Extension; def test_this_extension; end end
18
+ article = Doc()
19
+ MongoMapper::Document.append_extensions(Extension)
20
+ article.should respond_to(:test_this_extension)
21
+ end
22
+
23
+ should 'allow inclusions to Document to be appended' do
24
+ module Inclusion; def test_this_inclusion; end end
25
+ MongoMapper::Document.append_inclusions(Inclusion)
26
+ article = Doc()
27
+ article.new.should respond_to(:test_this_inclusion)
28
+ end
29
+
30
+ should 'add appended inclusions to classes that include Document before they are added' do
31
+ module Inclusion; def test_this_inclusion; end end
32
+ article = Doc()
33
+ MongoMapper::Document.append_inclusions(Inclusion)
34
+ article.new.should respond_to(:test_this_inclusion)
35
+ end
36
+ end
37
+
38
+ context "EmbeddedDocument" do
39
+ should "default descendants to a new set" do
40
+ MongoMapper::EmbeddedDocument.descendants.should be_instance_of(Set)
41
+ end
42
+
43
+ should 'allow extensions to Document to be appended' do
44
+ module Extension; def test_this_extension; end end
45
+ MongoMapper::EmbeddedDocument.append_extensions(Extension)
46
+ article = EDoc()
47
+ article.should respond_to(:test_this_extension)
48
+ end
49
+
50
+ should 'add appended extensions to classes that include Document before they are added' do
51
+ module Extension; def test_this_extension; end end
52
+ article = EDoc()
53
+ MongoMapper::EmbeddedDocument.append_extensions(Extension)
54
+ article.should respond_to(:test_this_extension)
55
+ end
56
+
57
+ should 'allow inclusions to Document to be appended' do
58
+ module Inclusion; def test_this_inclusion; end end
59
+ MongoMapper::EmbeddedDocument.append_inclusions(Inclusion)
60
+ article = EDoc()
61
+ article.new.should respond_to(:test_this_inclusion)
62
+ end
63
+
64
+ should 'add appended inclusions to classes that include Document before they are added' do
65
+ module Inclusion; def test_this_inclusion; end end
66
+ article = EDoc()
67
+ MongoMapper::EmbeddedDocument.append_inclusions(Inclusion)
68
+ article.new.should respond_to(:test_this_inclusion)
69
+ end
70
+ end
71
+ end
@@ -4,21 +4,17 @@ require 'models'
4
4
  class DocumentTest < Test::Unit::TestCase
5
5
  context "The Document Class" do
6
6
  setup do
7
- @document = Class.new do
8
- include MongoMapper::Document
9
- set_collection_name 'test'
10
- end
11
- @document.collection.remove
7
+ @document = Doc()
8
+ end
9
+
10
+ should "return false for embeddable" do
11
+ Doc().embeddable?.should be_false
12
12
  end
13
13
 
14
14
  should "have logger method" do
15
15
  @document.logger.should == MongoMapper.logger
16
16
  @document.logger.should be_instance_of(Logger)
17
17
  end
18
-
19
- should "track its descendants" do
20
- MongoMapper::Document.descendants.should include(@document)
21
- end
22
18
 
23
19
  should "use default database by default" do
24
20
  @document.database.should == MongoMapper.database
@@ -40,10 +36,7 @@ class DocumentTest < Test::Unit::TestCase
40
36
  @document.database_name.should == 'test2'
41
37
  @document.database.name.should == 'test2'
42
38
 
43
- another_document = Class.new do
44
- include MongoMapper::Document
45
- set_collection_name 'test'
46
- end
39
+ another_document = Doc()
47
40
  another_document.database.should == MongoMapper.database
48
41
  end
49
42
 
@@ -72,38 +65,6 @@ class DocumentTest < Test::Unit::TestCase
72
65
  @document.collection.should be_instance_of(Mongo::Collection)
73
66
  @document.collection.name.should == 'foobar'
74
67
  end
75
-
76
- should 'allow extensions to Document to be appended' do
77
- module Extension; def test_this_extension; end end
78
- MongoMapper::Document.append_extensions(Extension)
79
- article = Class.new { include MongoMapper::Document }
80
-
81
- article.should respond_to(:test_this_extension)
82
- end
83
-
84
- should 'add appended extensions to classes that include Document before they are added' do
85
- module Extension; def test_this_extension; end end
86
- article = Class.new { include MongoMapper::Document }
87
- MongoMapper::Document.append_extensions(Extension)
88
-
89
- article.should respond_to(:test_this_extension)
90
- end
91
-
92
- should 'allow inclusions to Document to be appended' do
93
- module Inclusion; def test_this_inclusion; end end
94
- MongoMapper::Document.append_inclusions(Inclusion)
95
- article = Class.new { include MongoMapper::Document }
96
-
97
- article.new.should respond_to(:test_this_inclusion)
98
- end
99
-
100
- should 'add appended inclusions to classes that include Document before they are added' do
101
- module Inclusion; def test_this_inclusion; end end
102
- article = Class.new { include MongoMapper::Document }
103
- MongoMapper::Document.append_inclusions(Inclusion)
104
-
105
- article.new.should respond_to(:test_this_inclusion)
106
- end
107
68
  end # Document class
108
69
 
109
70
  context "Documents that inherit from other documents" do
@@ -113,29 +74,41 @@ class DocumentTest < Test::Unit::TestCase
113
74
  Exit.collection_name.should == 'messages'
114
75
  Chat.collection_name.should == 'messages'
115
76
  end
116
-
77
+
117
78
  should "default associations to inherited class" do
118
- Message.associations.keys.should include("room")
119
- Enter.associations.keys.should include("room")
120
- Exit.associations.keys.should include("room")
121
- Chat.associations.keys.should include("room")
122
- end
123
-
124
- should "track subclasses" do
125
- Message.subclasses.should == [Enter, Exit, Chat]
79
+ Message.associations.keys.should include("room")
80
+ Enter.associations.keys.should include("room")
81
+ Exit.associations.keys.should include("room")
82
+ Chat.associations.keys.should include("room")
83
+ end
84
+ end
85
+
86
+ context "descendants" do
87
+ should "default to nil" do
88
+ Enter.descendants.should be_nil
89
+ end
90
+
91
+ should "be recorded" do
92
+ Message.descendants.should == [Enter, Exit, Chat]
126
93
  end
127
94
  end
128
95
 
129
96
  context "An instance of a document" do
130
97
  setup do
131
- @document = Class.new do
132
- include MongoMapper::Document
133
- set_collection_name 'test'
134
-
98
+ @document = Doc do
135
99
  key :name, String
136
100
  key :age, Integer
137
101
  end
138
- @document.collection.remove
102
+ end
103
+
104
+ should "create id during initialization" do
105
+ @document.new._id.should be_instance_of(Mongo::ObjectID)
106
+ end
107
+
108
+ should "have to_param that is string representation of id" do
109
+ doc = @document.new(:id => Mongo::ObjectID.new)
110
+ doc.to_param.should == doc.id.to_s
111
+ doc.to_param.should be_instance_of(String)
139
112
  end
140
113
 
141
114
  should "have access to logger" do
@@ -164,18 +137,10 @@ class DocumentTest < Test::Unit::TestCase
164
137
  end
165
138
 
166
139
  context "root document" do
167
- should "have a nil _root_document" do
168
- @document.new._root_document.should be_nil
169
- end
170
-
171
140
  should "set self to the root document on embedded documents" do
172
- klass = Class.new do
173
- include MongoMapper::Document
174
- end
141
+ klass = Doc()
142
+ pets = EDoc()
175
143
 
176
- pets = Class.new do
177
- include MongoMapper::EmbeddedDocument
178
- end
179
144
  klass.many :pets, :class => pets
180
145
 
181
146
  doc = klass.new(:pets => [{}])
@@ -197,7 +162,7 @@ class DocumentTest < Test::Unit::TestCase
197
162
  end
198
163
 
199
164
  context "clone" do
200
- should "not set the id" do
165
+ should "be new" do
201
166
  doc = @document.create(:name => "foo", :age => 27)
202
167
  clone = doc.clone
203
168
  clone.should be_new
@@ -211,10 +176,44 @@ class DocumentTest < Test::Unit::TestCase
211
176
  end
212
177
  end
213
178
 
179
+ should "call inspect on the document's attributes instead of to_s when inspecting the document" do
180
+ doc = @document.new(:animals => %w(dog cat))
181
+ doc.inspect.should include(%(animals: ["dog", "cat"]))
182
+ end
183
+
214
184
  context "equality" do
215
185
  setup do
216
186
  @oid = Mongo::ObjectID.new
217
187
  end
188
+
189
+ should "delegate hash to _id" do
190
+ doc = @document.new
191
+ doc.hash.should == doc._id.hash
192
+ end
193
+
194
+ should "delegate eql to ==" do
195
+ doc = @document.new
196
+ other = @document.new
197
+ doc.eql?(other).should == (doc == other)
198
+ doc.eql?(doc).should == (doc == doc)
199
+ end
200
+
201
+ should "know if same object as another" do
202
+ doc = @document.new
203
+ doc.should equal(doc)
204
+ doc.should_not equal(@document.new)
205
+ end
206
+
207
+ should "allow set operations on array of documents" do
208
+ @document.key :parent_id, ObjectId
209
+ @document.belongs_to :parent, :class => @document
210
+
211
+ parent = @document.create
212
+ child = @document.create(:parent => parent)
213
+
214
+ ([child.parent] & [parent]).should == [parent]
215
+ end
216
+
218
217
  should "be equal if id and class are the same" do
219
218
  (@document.new('_id' => @oid) == @document.new('_id' => @oid)).should be(true)
220
219
  end
@@ -224,12 +223,8 @@ class DocumentTest < Test::Unit::TestCase
224
223
  end
225
224
 
226
225
  should "not be equal if id same but class different" do
227
- @another_document = Class.new do
228
- include MongoMapper::Document
229
- set_collection_name 'test'
230
- end
231
-
232
- (@document.new('_id' => @oid) == @another_document.new('_id' => @oid)).should be(false)
226
+ another_document = Doc()
227
+ (@document.new('_id' => @oid) == another_document.new('_id' => @oid)).should be(false)
233
228
  end
234
229
  end
235
230
  end # instance of a document