drogus-mongo_mapper 0.6.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +10 -0
- data/LICENSE +20 -0
- data/README.rdoc +29 -0
- data/Rakefile +55 -0
- data/VERSION +1 -0
- data/bin/mmconsole +60 -0
- data/lib/mongo_mapper.rb +131 -0
- data/lib/mongo_mapper/document.rb +417 -0
- data/lib/mongo_mapper/embedded_document.rb +55 -0
- data/lib/mongo_mapper/finder_options.rb +127 -0
- data/lib/mongo_mapper/plugins.rb +30 -0
- data/lib/mongo_mapper/plugins/associations.rb +104 -0
- data/lib/mongo_mapper/plugins/associations/base.rb +121 -0
- data/lib/mongo_mapper/plugins/associations/belongs_to_polymorphic_proxy.rb +30 -0
- data/lib/mongo_mapper/plugins/associations/belongs_to_proxy.rb +25 -0
- data/lib/mongo_mapper/plugins/associations/collection.rb +21 -0
- data/lib/mongo_mapper/plugins/associations/embedded_collection.rb +50 -0
- data/lib/mongo_mapper/plugins/associations/in_array_proxy.rb +139 -0
- data/lib/mongo_mapper/plugins/associations/many_documents_as_proxy.rb +28 -0
- data/lib/mongo_mapper/plugins/associations/many_documents_proxy.rb +117 -0
- data/lib/mongo_mapper/plugins/associations/many_embedded_polymorphic_proxy.rb +31 -0
- data/lib/mongo_mapper/plugins/associations/many_embedded_proxy.rb +23 -0
- data/lib/mongo_mapper/plugins/associations/many_polymorphic_proxy.rb +13 -0
- data/lib/mongo_mapper/plugins/associations/one_proxy.rb +68 -0
- data/lib/mongo_mapper/plugins/associations/proxy.rb +118 -0
- data/lib/mongo_mapper/plugins/callbacks.rb +134 -0
- data/lib/mongo_mapper/plugins/clone.rb +13 -0
- data/lib/mongo_mapper/plugins/descendants.rb +16 -0
- data/lib/mongo_mapper/plugins/dirty.rb +119 -0
- data/lib/mongo_mapper/plugins/equality.rb +23 -0
- data/lib/mongo_mapper/plugins/identity_map.rb +122 -0
- data/lib/mongo_mapper/plugins/inspect.rb +14 -0
- data/lib/mongo_mapper/plugins/keys.rb +324 -0
- data/lib/mongo_mapper/plugins/logger.rb +17 -0
- data/lib/mongo_mapper/plugins/pagination.rb +85 -0
- data/lib/mongo_mapper/plugins/protected.rb +45 -0
- data/lib/mongo_mapper/plugins/rails.rb +45 -0
- data/lib/mongo_mapper/plugins/serialization.rb +105 -0
- data/lib/mongo_mapper/plugins/validations.rb +57 -0
- data/lib/mongo_mapper/support.rb +217 -0
- data/lib/mongo_mapper/support/descendant_appends.rb +46 -0
- data/lib/mongo_mapper/support/find.rb +77 -0
- data/mongo_mapper.gemspec +195 -0
- data/performance/read_write.rb +52 -0
- data/specs.watchr +51 -0
- data/test/NOTE_ON_TESTING +1 -0
- data/test/functional/associations/test_belongs_to_polymorphic_proxy.rb +63 -0
- data/test/functional/associations/test_belongs_to_proxy.rb +101 -0
- data/test/functional/associations/test_in_array_proxy.rb +309 -0
- data/test/functional/associations/test_many_documents_as_proxy.rb +229 -0
- data/test/functional/associations/test_many_documents_proxy.rb +431 -0
- data/test/functional/associations/test_many_embedded_polymorphic_proxy.rb +176 -0
- data/test/functional/associations/test_many_embedded_proxy.rb +256 -0
- data/test/functional/associations/test_many_polymorphic_proxy.rb +302 -0
- data/test/functional/associations/test_one_proxy.rb +161 -0
- data/test/functional/test_associations.rb +44 -0
- data/test/functional/test_binary.rb +27 -0
- data/test/functional/test_callbacks.rb +81 -0
- data/test/functional/test_dirty.rb +163 -0
- data/test/functional/test_document.rb +1264 -0
- data/test/functional/test_embedded_document.rb +125 -0
- data/test/functional/test_identity_map.rb +508 -0
- data/test/functional/test_logger.rb +20 -0
- data/test/functional/test_modifiers.rb +252 -0
- data/test/functional/test_pagination.rb +93 -0
- data/test/functional/test_protected.rb +155 -0
- data/test/functional/test_string_id_compatibility.rb +67 -0
- data/test/functional/test_validations.rb +329 -0
- data/test/models.rb +232 -0
- data/test/support/custom_matchers.rb +55 -0
- data/test/support/timing.rb +16 -0
- data/test/test_helper.rb +60 -0
- data/test/unit/associations/test_base.rb +207 -0
- data/test/unit/associations/test_proxy.rb +105 -0
- data/test/unit/serializers/test_json_serializer.rb +189 -0
- data/test/unit/test_descendant_appends.rb +71 -0
- data/test/unit/test_document.rb +231 -0
- data/test/unit/test_dynamic_finder.rb +123 -0
- data/test/unit/test_embedded_document.rb +663 -0
- data/test/unit/test_finder_options.rb +329 -0
- data/test/unit/test_keys.rb +169 -0
- data/test/unit/test_mongo_mapper.rb +65 -0
- data/test/unit/test_pagination.rb +127 -0
- data/test/unit/test_plugins.rb +50 -0
- data/test/unit/test_rails.rb +123 -0
- data/test/unit/test_rails_compatibility.rb +52 -0
- data/test/unit/test_serialization.rb +51 -0
- data/test/unit/test_support.rb +354 -0
- data/test/unit/test_time_zones.rb +39 -0
- data/test/unit/test_validations.rb +544 -0
- metadata +290 -0
@@ -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
|
@@ -0,0 +1,231 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'models'
|
3
|
+
|
4
|
+
class DocumentTest < Test::Unit::TestCase
|
5
|
+
context "The Document Class" do
|
6
|
+
setup do
|
7
|
+
@document = Doc()
|
8
|
+
end
|
9
|
+
|
10
|
+
should "return false for embeddable" do
|
11
|
+
Doc().embeddable?.should be_false
|
12
|
+
end
|
13
|
+
|
14
|
+
should "have logger method" do
|
15
|
+
@document.logger.should == MongoMapper.logger
|
16
|
+
@document.logger.should be_instance_of(Logger)
|
17
|
+
end
|
18
|
+
|
19
|
+
should "use default database by default" do
|
20
|
+
@document.database.should == MongoMapper.database
|
21
|
+
end
|
22
|
+
|
23
|
+
should "have a connection" do
|
24
|
+
@document.connection.should be_instance_of(Mongo::Connection)
|
25
|
+
end
|
26
|
+
|
27
|
+
should "allow setting different connection without affecting the default" do
|
28
|
+
conn = Mongo::Connection.new
|
29
|
+
@document.connection conn
|
30
|
+
@document.connection.should == conn
|
31
|
+
@document.connection.should_not == MongoMapper.connection
|
32
|
+
end
|
33
|
+
|
34
|
+
should "allow setting a different database without affecting the default" do
|
35
|
+
@document.set_database_name 'test2'
|
36
|
+
@document.database_name.should == 'test2'
|
37
|
+
@document.database.name.should == 'test2'
|
38
|
+
|
39
|
+
another_document = Doc()
|
40
|
+
another_document.database.should == MongoMapper.database
|
41
|
+
end
|
42
|
+
|
43
|
+
should "default collection name to class name tableized" do
|
44
|
+
class ::Item
|
45
|
+
include MongoMapper::Document
|
46
|
+
end
|
47
|
+
|
48
|
+
Item.collection.should be_instance_of(Mongo::Collection)
|
49
|
+
Item.collection.name.should == 'items'
|
50
|
+
end
|
51
|
+
|
52
|
+
should "default collection name of namespaced class to tableized with dot separation" do
|
53
|
+
module ::BloggyPoo
|
54
|
+
class Post
|
55
|
+
include MongoMapper::Document
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
BloggyPoo::Post.collection.should be_instance_of(Mongo::Collection)
|
60
|
+
BloggyPoo::Post.collection.name.should == 'bloggy_poo.posts'
|
61
|
+
end
|
62
|
+
|
63
|
+
should "allow setting the collection name" do
|
64
|
+
@document.set_collection_name('foobar')
|
65
|
+
@document.collection.should be_instance_of(Mongo::Collection)
|
66
|
+
@document.collection.name.should == 'foobar'
|
67
|
+
end
|
68
|
+
end # Document class
|
69
|
+
|
70
|
+
context "Documents that inherit from other documents" do
|
71
|
+
should "default collection name to inherited class" do
|
72
|
+
Message.collection_name.should == 'messages'
|
73
|
+
Enter.collection_name.should == 'messages'
|
74
|
+
Exit.collection_name.should == 'messages'
|
75
|
+
Chat.collection_name.should == 'messages'
|
76
|
+
end
|
77
|
+
|
78
|
+
should "default associations to inherited class" do
|
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]
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
context "An instance of a document" do
|
97
|
+
setup do
|
98
|
+
@document = Doc do
|
99
|
+
key :name, String
|
100
|
+
key :age, Integer
|
101
|
+
end
|
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)
|
112
|
+
end
|
113
|
+
|
114
|
+
should "have access to logger" do
|
115
|
+
doc = @document.new
|
116
|
+
doc.logger.should == @document.logger
|
117
|
+
doc.logger.should be_instance_of(Logger)
|
118
|
+
end
|
119
|
+
|
120
|
+
should "have access to the class's collection" do
|
121
|
+
doc = @document.new
|
122
|
+
doc.collection.name.should == @document.collection.name
|
123
|
+
end
|
124
|
+
|
125
|
+
should "use default values if defined for keys" do
|
126
|
+
@document.key :active, Boolean, :default => true
|
127
|
+
|
128
|
+
@document.new.active.should be_true
|
129
|
+
@document.new(:active => false).active.should be_false
|
130
|
+
end
|
131
|
+
|
132
|
+
should "use default values if defined even when custom data type" do
|
133
|
+
@document.key :window, WindowSize, :default => WindowSize.new(600, 480)
|
134
|
+
|
135
|
+
doc = @document.new
|
136
|
+
doc.window.should == WindowSize.new(600, 480)
|
137
|
+
end
|
138
|
+
|
139
|
+
context "root document" do
|
140
|
+
should "set self to the root document on embedded documents" do
|
141
|
+
klass = Doc()
|
142
|
+
pets = EDoc()
|
143
|
+
|
144
|
+
klass.many :pets, :class => pets
|
145
|
+
|
146
|
+
doc = klass.new(:pets => [{}])
|
147
|
+
doc.pets.first._root_document.should == doc
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
context "new?" do
|
152
|
+
should "be true if no id" do
|
153
|
+
@document.new.new?.should be_true
|
154
|
+
end
|
155
|
+
|
156
|
+
should "be true if id but using custom id and not saved yet" do
|
157
|
+
@document.key :_id, String
|
158
|
+
doc = @document.new
|
159
|
+
doc.id = '1234'
|
160
|
+
doc.new?.should be_true
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
context "clone" do
|
165
|
+
should "be new" do
|
166
|
+
doc = @document.create(:name => "foo", :age => 27)
|
167
|
+
clone = doc.clone
|
168
|
+
clone.should be_new
|
169
|
+
end
|
170
|
+
|
171
|
+
should "copy the attributes" do
|
172
|
+
doc = @document.create(:name => "foo", :age => 27)
|
173
|
+
clone = doc.clone
|
174
|
+
clone.name.should == "foo"
|
175
|
+
clone.age.should == 27
|
176
|
+
end
|
177
|
+
end
|
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
|
+
|
184
|
+
context "equality" do
|
185
|
+
setup do
|
186
|
+
@oid = Mongo::ObjectID.new
|
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
|
+
|
217
|
+
should "be equal if id and class are the same" do
|
218
|
+
(@document.new('_id' => @oid) == @document.new('_id' => @oid)).should be(true)
|
219
|
+
end
|
220
|
+
|
221
|
+
should "not be equal if class same but id different" do
|
222
|
+
(@document.new('_id' => @oid) == @document.new('_id' => Mongo::ObjectID.new)).should be(false)
|
223
|
+
end
|
224
|
+
|
225
|
+
should "not be equal if id same but class different" do
|
226
|
+
another_document = Doc()
|
227
|
+
(@document.new('_id' => @oid) == another_document.new('_id' => @oid)).should be(false)
|
228
|
+
end
|
229
|
+
end
|
230
|
+
end # instance of a document
|
231
|
+
end # DocumentTest
|
@@ -0,0 +1,123 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class DynamicFinderTest < Test::Unit::TestCase
|
4
|
+
should "initialize with method" do
|
5
|
+
finder = MongoMapper::Support::Find::DynamicFinder.new(:foobar)
|
6
|
+
finder.method.should == :foobar
|
7
|
+
end
|
8
|
+
|
9
|
+
context "found?" do
|
10
|
+
should "be true for find_by" do
|
11
|
+
MongoMapper::Support::Find::DynamicFinder.new(:find_by_foo).found?.should be_true
|
12
|
+
end
|
13
|
+
|
14
|
+
should "be true for find_by with !" do
|
15
|
+
MongoMapper::Support::Find::DynamicFinder.new(:find_by_foo!).found?.should be_true
|
16
|
+
end
|
17
|
+
|
18
|
+
should "be true for find_all_by" do
|
19
|
+
MongoMapper::Support::Find::DynamicFinder.new(:find_all_by_foo).found?.should be_true
|
20
|
+
end
|
21
|
+
|
22
|
+
should "be true for find_or_initialize_by" do
|
23
|
+
MongoMapper::Support::Find::DynamicFinder.new(:find_or_initialize_by_foo).found?.should be_true
|
24
|
+
end
|
25
|
+
|
26
|
+
should "be true for find_or_create_by" do
|
27
|
+
MongoMapper::Support::Find::DynamicFinder.new(:find_or_create_by_foo).found?.should be_true
|
28
|
+
end
|
29
|
+
|
30
|
+
should "be false for anything else" do
|
31
|
+
[:foobar, :bazwick].each do |method|
|
32
|
+
MongoMapper::Support::Find::DynamicFinder.new(method).found?.should be_false
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context "find_all_by" do
|
38
|
+
should "parse one attribute" do
|
39
|
+
MongoMapper::Support::Find::DynamicFinder.new(:find_all_by_foo).attributes.should == %w(foo)
|
40
|
+
end
|
41
|
+
|
42
|
+
should "parse multiple attributes" do
|
43
|
+
MongoMapper::Support::Find::DynamicFinder.new(:find_all_by_foo_and_bar).attributes.should == %w(foo bar)
|
44
|
+
MongoMapper::Support::Find::DynamicFinder.new(:find_all_by_foo_and_bar_and_baz).attributes.should == %w(foo bar baz)
|
45
|
+
end
|
46
|
+
|
47
|
+
should "set finder to :all" do
|
48
|
+
MongoMapper::Support::Find::DynamicFinder.new(:find_all_by_foo_and_bar).finder.should == :all
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context "find_by" do
|
53
|
+
should "parse one attribute" do
|
54
|
+
MongoMapper::Support::Find::DynamicFinder.new(:find_by_foo).attributes.should == %w(foo)
|
55
|
+
end
|
56
|
+
|
57
|
+
should "parse multiple attributes" do
|
58
|
+
MongoMapper::Support::Find::DynamicFinder.new(:find_by_foo_and_bar).attributes.should == %w(foo bar)
|
59
|
+
end
|
60
|
+
|
61
|
+
should "set finder to :first" do
|
62
|
+
MongoMapper::Support::Find::DynamicFinder.new(:find_by_foo).finder.should == :first
|
63
|
+
end
|
64
|
+
|
65
|
+
should "set bang to false" do
|
66
|
+
MongoMapper::Support::Find::DynamicFinder.new(:find_by_foo).bang.should be_false
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
context "find_by with !" do
|
71
|
+
should "parse one attribute" do
|
72
|
+
MongoMapper::Support::Find::DynamicFinder.new(:find_by_foo!).attributes.should == %w(foo)
|
73
|
+
end
|
74
|
+
|
75
|
+
should "parse multiple attributes" do
|
76
|
+
MongoMapper::Support::Find::DynamicFinder.new(:find_by_foo_and_bar!).attributes.should == %w(foo bar)
|
77
|
+
end
|
78
|
+
|
79
|
+
should "set finder to :first" do
|
80
|
+
MongoMapper::Support::Find::DynamicFinder.new(:find_by_foo!).finder.should == :first
|
81
|
+
end
|
82
|
+
|
83
|
+
should "set bang to true" do
|
84
|
+
MongoMapper::Support::Find::DynamicFinder.new(:find_by_foo!).bang.should be_true
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
context "find_or_initialize_by" do
|
89
|
+
should "parse one attribute" do
|
90
|
+
MongoMapper::Support::Find::DynamicFinder.new(:find_or_initialize_by_foo).attributes.should == %w(foo)
|
91
|
+
end
|
92
|
+
|
93
|
+
should "parse multiple attributes" do
|
94
|
+
MongoMapper::Support::Find::DynamicFinder.new(:find_or_initialize_by_foo_and_bar).attributes.should == %w(foo bar)
|
95
|
+
end
|
96
|
+
|
97
|
+
should "set finder to :first" do
|
98
|
+
MongoMapper::Support::Find::DynamicFinder.new(:find_or_initialize_by_foo).finder.should == :first
|
99
|
+
end
|
100
|
+
|
101
|
+
should "set instantiator to new" do
|
102
|
+
MongoMapper::Support::Find::DynamicFinder.new(:find_or_initialize_by_foo).instantiator.should == :new
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
context "find_or_create_by" do
|
107
|
+
should "parse one attribute" do
|
108
|
+
MongoMapper::Support::Find::DynamicFinder.new(:find_or_create_by_foo).attributes.should == %w(foo)
|
109
|
+
end
|
110
|
+
|
111
|
+
should "parse multiple attributes" do
|
112
|
+
MongoMapper::Support::Find::DynamicFinder.new(:find_or_create_by_foo_and_bar).attributes.should == %w(foo bar)
|
113
|
+
end
|
114
|
+
|
115
|
+
should "set finder to :first" do
|
116
|
+
MongoMapper::Support::Find::DynamicFinder.new(:find_or_create_by_foo).finder.should == :first
|
117
|
+
end
|
118
|
+
|
119
|
+
should "set instantiator to new" do
|
120
|
+
MongoMapper::Support::Find::DynamicFinder.new(:find_or_create_by_foo).instantiator.should == :create
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
@@ -0,0 +1,663 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module KeyOverride
|
4
|
+
def other_child
|
5
|
+
self[:other_child] || "special result"
|
6
|
+
end
|
7
|
+
|
8
|
+
def other_child=(value)
|
9
|
+
super(value + " modified")
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class EmbeddedDocumentTest < Test::Unit::TestCase
|
14
|
+
context "" do
|
15
|
+
setup do
|
16
|
+
class ::Grandparent
|
17
|
+
include MongoMapper::EmbeddedDocument
|
18
|
+
key :grandparent, String
|
19
|
+
end
|
20
|
+
|
21
|
+
class ::Parent < ::Grandparent
|
22
|
+
include MongoMapper::EmbeddedDocument
|
23
|
+
key :parent, String
|
24
|
+
end
|
25
|
+
|
26
|
+
class ::Child < ::Parent
|
27
|
+
include MongoMapper::EmbeddedDocument
|
28
|
+
key :child, String
|
29
|
+
end
|
30
|
+
|
31
|
+
class ::OtherChild < ::Parent
|
32
|
+
include MongoMapper::EmbeddedDocument
|
33
|
+
include KeyOverride
|
34
|
+
|
35
|
+
key :other_child, String
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
teardown do
|
40
|
+
Object.send :remove_const, 'Grandparent' if defined?(::Grandparent)
|
41
|
+
Object.send :remove_const, 'Parent' if defined?(::Parent)
|
42
|
+
Object.send :remove_const, 'Child' if defined?(::Child)
|
43
|
+
Object.send :remove_const, 'OtherChild' if defined?(::OtherChild)
|
44
|
+
end
|
45
|
+
|
46
|
+
context "Including MongoMapper::EmbeddedDocument in a class" do
|
47
|
+
setup do
|
48
|
+
@klass = EDoc()
|
49
|
+
end
|
50
|
+
|
51
|
+
should "add _id key" do
|
52
|
+
@klass.keys['_id'].should_not be_nil
|
53
|
+
end
|
54
|
+
|
55
|
+
should "know it is using object id" do
|
56
|
+
@klass.using_object_id?.should be_true
|
57
|
+
end
|
58
|
+
|
59
|
+
should "know it is not using object id if _id type is changed" do
|
60
|
+
@klass.key :_id, String
|
61
|
+
@klass.using_object_id?.should be_false
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
context "Class Methods" do
|
66
|
+
should "include logger" do
|
67
|
+
@klass = EDoc()
|
68
|
+
@klass.logger.should == MongoMapper.logger
|
69
|
+
@klass.logger.should be_instance_of(Logger)
|
70
|
+
end
|
71
|
+
|
72
|
+
should "return false for embeddable" do
|
73
|
+
EDoc().embeddable?.should be_true
|
74
|
+
end
|
75
|
+
|
76
|
+
context "#to_mongo" do
|
77
|
+
setup { @klass = EDoc() }
|
78
|
+
|
79
|
+
should "be nil if nil" do
|
80
|
+
@klass.to_mongo(nil).should be_nil
|
81
|
+
end
|
82
|
+
|
83
|
+
should "convert to_mongo for other values" do
|
84
|
+
doc = @klass.new(:foo => 'bar')
|
85
|
+
to_mongo = @klass.to_mongo(doc)
|
86
|
+
to_mongo.is_a?(Hash).should be_true
|
87
|
+
to_mongo['foo'].should == 'bar'
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
context "#from_mongo" do
|
92
|
+
setup { @klass = EDoc() }
|
93
|
+
|
94
|
+
should "be nil if nil" do
|
95
|
+
@klass.from_mongo(nil).should be_nil
|
96
|
+
end
|
97
|
+
|
98
|
+
should "be instance if instance of class" do
|
99
|
+
doc = @klass.new
|
100
|
+
@klass.from_mongo(doc).should == doc
|
101
|
+
end
|
102
|
+
|
103
|
+
should "be instance if hash of attributes" do
|
104
|
+
doc = @klass.from_mongo({:foo => 'bar'})
|
105
|
+
doc.instance_of?(@klass).should be_true
|
106
|
+
doc.foo.should == 'bar'
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
context "defining a key" do
|
111
|
+
setup do
|
112
|
+
@document = EDoc()
|
113
|
+
end
|
114
|
+
|
115
|
+
should "work with name" do
|
116
|
+
key = @document.key(:name)
|
117
|
+
key.name.should == 'name'
|
118
|
+
end
|
119
|
+
|
120
|
+
should "work with name and type" do
|
121
|
+
key = @document.key(:name, String)
|
122
|
+
key.name.should == 'name'
|
123
|
+
key.type.should == String
|
124
|
+
end
|
125
|
+
|
126
|
+
should "work with name, type and options" do
|
127
|
+
key = @document.key(:name, String, :required => true)
|
128
|
+
key.name.should == 'name'
|
129
|
+
key.type.should == String
|
130
|
+
key.options[:required].should be_true
|
131
|
+
end
|
132
|
+
|
133
|
+
should "work with name and options" do
|
134
|
+
key = @document.key(:name, :required => true)
|
135
|
+
key.name.should == 'name'
|
136
|
+
key.options[:required].should be_true
|
137
|
+
end
|
138
|
+
|
139
|
+
should "be tracked per document" do
|
140
|
+
@document.key(:name, String)
|
141
|
+
@document.key(:age, Integer)
|
142
|
+
@document.keys['name'].name.should == 'name'
|
143
|
+
@document.keys['name'].type.should == String
|
144
|
+
@document.keys['age'].name.should == 'age'
|
145
|
+
@document.keys['age'].type.should == Integer
|
146
|
+
end
|
147
|
+
|
148
|
+
should "be redefinable" do
|
149
|
+
@document.key(:foo, String)
|
150
|
+
@document.keys['foo'].type.should == String
|
151
|
+
@document.key(:foo, Integer)
|
152
|
+
@document.keys['foo'].type.should == Integer
|
153
|
+
end
|
154
|
+
|
155
|
+
should "create reader method" do
|
156
|
+
@document.new.should_not respond_to(:foo)
|
157
|
+
@document.key(:foo, String)
|
158
|
+
@document.new.should respond_to(:foo)
|
159
|
+
end
|
160
|
+
|
161
|
+
should "create reader before typecast method" do
|
162
|
+
@document.new.should_not respond_to(:foo_before_typecast)
|
163
|
+
@document.key(:foo, String)
|
164
|
+
@document.new.should respond_to(:foo_before_typecast)
|
165
|
+
end
|
166
|
+
|
167
|
+
should "create writer method" do
|
168
|
+
@document.new.should_not respond_to(:foo=)
|
169
|
+
@document.key(:foo, String)
|
170
|
+
@document.new.should respond_to(:foo=)
|
171
|
+
end
|
172
|
+
|
173
|
+
should "create boolean method" do
|
174
|
+
@document.new.should_not respond_to(:foo?)
|
175
|
+
@document.key(:foo, String)
|
176
|
+
@document.new.should respond_to(:foo?)
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
context "keys" do
|
181
|
+
should "be inherited" do
|
182
|
+
Grandparent.keys.keys.sort.should == ['_id', 'grandparent']
|
183
|
+
Parent.keys.keys.sort.should == ['_id', 'grandparent', 'parent']
|
184
|
+
Child.keys.keys.sort.should == ['_id', 'child', 'grandparent', 'parent']
|
185
|
+
end
|
186
|
+
|
187
|
+
should "propogate to descendants if key added after class definition" do
|
188
|
+
Grandparent.key :_type, String
|
189
|
+
|
190
|
+
Grandparent.keys.keys.sort.should == ['_id', '_type', 'grandparent']
|
191
|
+
Parent.keys.keys.sort.should == ['_id', '_type', 'grandparent', 'parent']
|
192
|
+
Child.keys.keys.sort.should == ['_id', '_type', 'child', 'grandparent', 'parent']
|
193
|
+
end
|
194
|
+
|
195
|
+
should "not add anonymous objects to the ancestor tree" do
|
196
|
+
OtherChild.ancestors.any? { |a| a.name.blank? }.should be_false
|
197
|
+
end
|
198
|
+
|
199
|
+
should "not include descendant keys" do
|
200
|
+
lambda { Parent.new.other_child }.should raise_error
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
context "descendants" do
|
205
|
+
should "default to nil" do
|
206
|
+
Child.descendants.should be_nil
|
207
|
+
end
|
208
|
+
|
209
|
+
should "be recorded" do
|
210
|
+
Grandparent.descendants.should == [Parent]
|
211
|
+
Parent.descendants.should == [Child, OtherChild]
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
context "An instance of an embedded document" do
|
217
|
+
setup do
|
218
|
+
@document = EDoc do
|
219
|
+
key :name, String
|
220
|
+
key :age, Integer
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
should "have to_param that is string representation of id" do
|
225
|
+
doc = @document.new
|
226
|
+
doc.to_param.should == doc.id.to_s
|
227
|
+
doc.to_param.should be_instance_of(String)
|
228
|
+
end
|
229
|
+
|
230
|
+
should "have access to class logger" do
|
231
|
+
doc = @document.new
|
232
|
+
doc.logger.should == @document.logger
|
233
|
+
doc.logger.should be_instance_of(Logger)
|
234
|
+
end
|
235
|
+
|
236
|
+
should "automatically have an _id key" do
|
237
|
+
@document.keys.keys.should include('_id')
|
238
|
+
end
|
239
|
+
|
240
|
+
should "create id during initialization" do
|
241
|
+
@document.new._id.should be_instance_of(Mongo::ObjectID)
|
242
|
+
end
|
243
|
+
|
244
|
+
should "have id method returns _id" do
|
245
|
+
id = Mongo::ObjectID.new
|
246
|
+
doc = @document.new(:_id => id)
|
247
|
+
doc.id.should == id
|
248
|
+
end
|
249
|
+
|
250
|
+
should "convert string object id to mongo object id when assigning id with _id object id type" do
|
251
|
+
id = Mongo::ObjectID.new
|
252
|
+
|
253
|
+
doc = @document.new(:id => id.to_s)
|
254
|
+
doc._id.should == id
|
255
|
+
doc.id.should == id
|
256
|
+
|
257
|
+
doc = @document.new(:_id => id.to_s)
|
258
|
+
doc._id.should == id
|
259
|
+
doc.id.should == id
|
260
|
+
end
|
261
|
+
|
262
|
+
context "_root_document" do
|
263
|
+
should "default to nil" do
|
264
|
+
@document.new._root_document.should be_nil
|
265
|
+
end
|
266
|
+
|
267
|
+
should "allow setting when initialized" do
|
268
|
+
root = Doc().new
|
269
|
+
doc = @document.new :_root_document => root
|
270
|
+
|
271
|
+
doc._root_document.should be(root)
|
272
|
+
end
|
273
|
+
|
274
|
+
should "also be set on many embedded documents" do
|
275
|
+
root = Doc().new
|
276
|
+
klass = EDoc { many :children }
|
277
|
+
doc = klass.new(:_root_document => root, :children => [{}])
|
278
|
+
|
279
|
+
doc.children.first._root_document.should == root
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
context "being initialized" do
|
284
|
+
should "accept a hash that sets keys and values" do
|
285
|
+
doc = @document.new(:name => 'John', :age => 23)
|
286
|
+
doc.attributes.keys.sort.should == ['_id', 'age', 'name']
|
287
|
+
doc.attributes['name'].should == 'John'
|
288
|
+
doc.attributes['age'].should == 23
|
289
|
+
end
|
290
|
+
|
291
|
+
should "be able to assign keys dynamically" do
|
292
|
+
doc = @document.new(:name => 'John', :skills => ['ruby', 'rails'])
|
293
|
+
doc.name.should == 'John'
|
294
|
+
doc.skills.should == ['ruby', 'rails']
|
295
|
+
end
|
296
|
+
|
297
|
+
should "not throw error if initialized with nil" do
|
298
|
+
assert_nothing_raised { @document.new(nil) }
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
302
|
+
context "initialized when _type key present" do
|
303
|
+
setup do
|
304
|
+
@klass = EDoc('FooBar') { key :_type, String }
|
305
|
+
end
|
306
|
+
|
307
|
+
should "set _type to class name" do
|
308
|
+
@klass.new._type.should == 'FooBar'
|
309
|
+
end
|
310
|
+
|
311
|
+
should "not change _type if already set" do
|
312
|
+
@klass.new(:_type => 'Foo')._type.should == 'Foo'
|
313
|
+
end
|
314
|
+
end
|
315
|
+
|
316
|
+
context "attributes=" do
|
317
|
+
should "update values for keys provided" do
|
318
|
+
doc = @document.new(:name => 'foobar', :age => 10)
|
319
|
+
doc.attributes = {:name => 'new value', :age => 5}
|
320
|
+
doc.attributes[:name].should == 'new value'
|
321
|
+
doc.attributes[:age].should == 5
|
322
|
+
end
|
323
|
+
|
324
|
+
should "not update values for keys that were not provided" do
|
325
|
+
doc = @document.new(:name => 'foobar', :age => 10)
|
326
|
+
doc.attributes = {:name => 'new value'}
|
327
|
+
doc.attributes[:name].should == 'new value'
|
328
|
+
doc.attributes[:age].should == 10
|
329
|
+
end
|
330
|
+
|
331
|
+
should "work with pre-defined methods" do
|
332
|
+
@document.class_eval do
|
333
|
+
attr_writer :password
|
334
|
+
|
335
|
+
def passwd
|
336
|
+
@password
|
337
|
+
end
|
338
|
+
end
|
339
|
+
|
340
|
+
doc = @document.new(:name => 'foobar', :password => 'secret')
|
341
|
+
doc.passwd.should == 'secret'
|
342
|
+
end
|
343
|
+
|
344
|
+
should "typecast key values" do
|
345
|
+
doc = @document.new(:name => 1234, :age => '21')
|
346
|
+
doc.name.should == '1234'
|
347
|
+
doc.age.should == 21
|
348
|
+
end
|
349
|
+
end
|
350
|
+
|
351
|
+
context "attributes" do
|
352
|
+
should "default to hash with all keys" do
|
353
|
+
doc = @document.new
|
354
|
+
doc.attributes.keys.sort.should == ['_id', 'age', 'name']
|
355
|
+
end
|
356
|
+
|
357
|
+
should "return all keys with values" do
|
358
|
+
doc = @document.new(:name => 'string', :age => nil)
|
359
|
+
doc.attributes.keys.sort.should == ['_id', 'age', 'name']
|
360
|
+
doc.attributes.values.should include('string')
|
361
|
+
doc.attributes.values.should include(nil)
|
362
|
+
end
|
363
|
+
|
364
|
+
should "have indifferent access" do
|
365
|
+
doc = @document.new(:name => 'string')
|
366
|
+
doc.attributes[:name].should == 'string'
|
367
|
+
doc.attributes['name'].should == 'string'
|
368
|
+
end
|
369
|
+
end
|
370
|
+
|
371
|
+
context "to_mongo" do
|
372
|
+
should "default to hash with _id key" do
|
373
|
+
doc = @document.new
|
374
|
+
doc.to_mongo.keys.sort.should == ['_id', 'age', 'name']
|
375
|
+
end
|
376
|
+
|
377
|
+
should "return all keys" do
|
378
|
+
doc = @document.new(:name => 'string', :age => nil)
|
379
|
+
doc.to_mongo.keys.sort.should == ['_id', 'age', 'name']
|
380
|
+
doc.to_mongo.values.should include('string')
|
381
|
+
doc.to_mongo.values.should include(nil)
|
382
|
+
end
|
383
|
+
end
|
384
|
+
|
385
|
+
context "clone" do
|
386
|
+
should "regenerate the id" do
|
387
|
+
doc = @document.new(:name => "foo", :age => 27)
|
388
|
+
doc_id = doc.id
|
389
|
+
clone = doc.clone
|
390
|
+
clone_id = clone.id
|
391
|
+
clone_id.should_not == doc_id
|
392
|
+
end
|
393
|
+
|
394
|
+
should "copy the attributes" do
|
395
|
+
doc = @document.new(:name => "foo", :age => 27)
|
396
|
+
clone = doc.clone
|
397
|
+
clone.name.should == "foo"
|
398
|
+
clone.age.should == 27
|
399
|
+
end
|
400
|
+
end
|
401
|
+
|
402
|
+
context "key shorcut access" do
|
403
|
+
context "[]" do
|
404
|
+
should "work when key found" do
|
405
|
+
doc = @document.new(:name => 'string')
|
406
|
+
doc[:name].should == 'string'
|
407
|
+
end
|
408
|
+
|
409
|
+
should "raise exception when key not found" do
|
410
|
+
doc = @document.new(:name => 'string')
|
411
|
+
assert_raises(MongoMapper::KeyNotFound) { doc[:not_here] }
|
412
|
+
end
|
413
|
+
end
|
414
|
+
|
415
|
+
context "[]=" do
|
416
|
+
should "write key value for existing key" do
|
417
|
+
doc = @document.new
|
418
|
+
doc[:name] = 'string'
|
419
|
+
doc[:name].should == 'string'
|
420
|
+
end
|
421
|
+
|
422
|
+
should "create key and write value for missing key" do
|
423
|
+
doc = @document.new
|
424
|
+
doc[:foo] = 'string'
|
425
|
+
doc.class.keys.include?('foo').should be_true
|
426
|
+
doc[:foo].should == 'string'
|
427
|
+
end
|
428
|
+
|
429
|
+
should "share the new key with the class" do
|
430
|
+
doc = @document.new
|
431
|
+
doc[:foo] = 'string'
|
432
|
+
@document.keys.should include('foo')
|
433
|
+
end
|
434
|
+
end
|
435
|
+
end
|
436
|
+
|
437
|
+
context "reading a key" do
|
438
|
+
should "work for defined keys" do
|
439
|
+
doc = @document.new(:name => 'string')
|
440
|
+
doc.name.should == 'string'
|
441
|
+
end
|
442
|
+
|
443
|
+
should "raise no method error for undefined keys" do
|
444
|
+
doc = @document.new
|
445
|
+
lambda { doc.fart }.should raise_error(NoMethodError)
|
446
|
+
end
|
447
|
+
|
448
|
+
should "be accessible for use in the model" do
|
449
|
+
@document.class_eval do
|
450
|
+
def name_and_age
|
451
|
+
"#{self[:name]} (#{self[:age]})"
|
452
|
+
end
|
453
|
+
end
|
454
|
+
|
455
|
+
doc = @document.new(:name => 'John', :age => 27)
|
456
|
+
doc.name_and_age.should == 'John (27)'
|
457
|
+
end
|
458
|
+
|
459
|
+
should "set instance variable" do
|
460
|
+
@document.key :foo, Array
|
461
|
+
doc = @document.new
|
462
|
+
doc.instance_variable_get("@foo").should be_nil
|
463
|
+
doc.foo
|
464
|
+
doc.instance_variable_get("@foo").should == []
|
465
|
+
end
|
466
|
+
|
467
|
+
should "be overrideable by modules" do
|
468
|
+
@document = Doc do
|
469
|
+
key :other_child, String
|
470
|
+
end
|
471
|
+
|
472
|
+
child = @document.new
|
473
|
+
child.other_child.should be_nil
|
474
|
+
|
475
|
+
@document.send :include, KeyOverride
|
476
|
+
|
477
|
+
overriden_child = @document.new
|
478
|
+
overriden_child.other_child.should == 'special result'
|
479
|
+
end
|
480
|
+
end
|
481
|
+
|
482
|
+
context "reading a key before typcasting" do
|
483
|
+
should "work for defined keys" do
|
484
|
+
doc = @document.new(:name => 12)
|
485
|
+
doc.name_before_typecast.should == 12
|
486
|
+
end
|
487
|
+
|
488
|
+
should "raise no method error for undefined keys" do
|
489
|
+
doc = @document.new
|
490
|
+
lambda { doc.foo_before_typecast }.should raise_error(NoMethodError)
|
491
|
+
end
|
492
|
+
|
493
|
+
should "be accessible for use in a document" do
|
494
|
+
@document.class_eval do
|
495
|
+
def untypcasted_name
|
496
|
+
read_key_before_typecast(:name)
|
497
|
+
end
|
498
|
+
end
|
499
|
+
|
500
|
+
doc = @document.new(:name => 12)
|
501
|
+
doc.name.should == '12'
|
502
|
+
doc.untypcasted_name.should == 12
|
503
|
+
end
|
504
|
+
end
|
505
|
+
|
506
|
+
context "writing a key" do
|
507
|
+
should "work for defined keys" do
|
508
|
+
doc = @document.new
|
509
|
+
doc.name = 'John'
|
510
|
+
doc.name.should == 'John'
|
511
|
+
end
|
512
|
+
|
513
|
+
should "raise no method error for undefined keys" do
|
514
|
+
doc = @document.new
|
515
|
+
lambda { doc.fart = 'poof!' }.should raise_error(NoMethodError)
|
516
|
+
end
|
517
|
+
|
518
|
+
should "typecast value" do
|
519
|
+
doc = @document.new
|
520
|
+
doc.name = 1234
|
521
|
+
doc.name.should == '1234'
|
522
|
+
doc.age = '21'
|
523
|
+
doc.age.should == 21
|
524
|
+
end
|
525
|
+
|
526
|
+
should "be accessible for use in the model" do
|
527
|
+
@document.class_eval do
|
528
|
+
def name_and_age=(new_value)
|
529
|
+
new_value.match(/([^\(\s]+) \((.*)\)/)
|
530
|
+
write_key :name, $1
|
531
|
+
write_key :age, $2
|
532
|
+
end
|
533
|
+
end
|
534
|
+
|
535
|
+
doc = @document.new
|
536
|
+
doc.name_and_age = 'Frank (62)'
|
537
|
+
doc.name.should == 'Frank'
|
538
|
+
doc.age.should == 62
|
539
|
+
end
|
540
|
+
|
541
|
+
should "be overrideable by modules" do
|
542
|
+
@document = Doc do
|
543
|
+
key :other_child, String
|
544
|
+
end
|
545
|
+
|
546
|
+
child = @document.new(:other_child => 'foo')
|
547
|
+
child.other_child.should == 'foo'
|
548
|
+
|
549
|
+
@document.send :include, KeyOverride
|
550
|
+
|
551
|
+
overriden_child = @document.new(:other_child => 'foo')
|
552
|
+
overriden_child.other_child.should == 'foo modified'
|
553
|
+
end
|
554
|
+
end # writing a key
|
555
|
+
|
556
|
+
context "checking if a keys value is present" do
|
557
|
+
should "work for defined keys" do
|
558
|
+
doc = @document.new
|
559
|
+
doc.name?.should be_false
|
560
|
+
doc.name = 'John'
|
561
|
+
doc.name?.should be_true
|
562
|
+
end
|
563
|
+
|
564
|
+
should "raise no method error for undefined keys" do
|
565
|
+
doc = @document.new
|
566
|
+
lambda { doc.fart? }.should raise_error(NoMethodError)
|
567
|
+
end
|
568
|
+
end
|
569
|
+
|
570
|
+
should "call inspect on the document's attributes instead of to_s when inspecting the document" do
|
571
|
+
doc = @document.new(:animals => %w(dog cat))
|
572
|
+
doc.inspect.should include(%(animals: ["dog", "cat"]))
|
573
|
+
end
|
574
|
+
|
575
|
+
context "equality" do
|
576
|
+
setup do
|
577
|
+
@oid = Mongo::ObjectID.new
|
578
|
+
end
|
579
|
+
|
580
|
+
should "delegate hash to _id" do
|
581
|
+
doc = @document.new
|
582
|
+
doc.hash.should == doc._id.hash
|
583
|
+
end
|
584
|
+
|
585
|
+
should "delegate eql to ==" do
|
586
|
+
doc = @document.new
|
587
|
+
other = @document.new
|
588
|
+
doc.eql?(other).should == (doc == other)
|
589
|
+
doc.eql?(doc).should == (doc == doc)
|
590
|
+
end
|
591
|
+
|
592
|
+
should "know if same object as another" do
|
593
|
+
doc = @document.new
|
594
|
+
doc.should equal(doc)
|
595
|
+
doc.should_not equal(@document.new)
|
596
|
+
end
|
597
|
+
|
598
|
+
should "allow set operations on array of documents" do
|
599
|
+
doc = @document.new
|
600
|
+
([doc] & [doc]).should == [doc]
|
601
|
+
end
|
602
|
+
|
603
|
+
should "be equal if id and class are the same" do
|
604
|
+
(@document.new('_id' => @oid) == @document.new('_id' => @oid)).should be_true
|
605
|
+
end
|
606
|
+
|
607
|
+
should "not be equal if class same but id different" do
|
608
|
+
(@document.new('_id' => @oid) == @document.new('_id' => Mongo::ObjectID.new)).should be_false
|
609
|
+
end
|
610
|
+
|
611
|
+
should "not be equal if id same but class different" do
|
612
|
+
another_document = Doc()
|
613
|
+
(@document.new('_id' => @oid) == another_document.new('_id' => @oid)).should be_false
|
614
|
+
end
|
615
|
+
end
|
616
|
+
|
617
|
+
context "reading keys with default values" do
|
618
|
+
setup do
|
619
|
+
@document = EDoc do
|
620
|
+
key :name, String, :default => 'foo'
|
621
|
+
key :age, Integer, :default => 20
|
622
|
+
key :net_worth, Float, :default => 100.00
|
623
|
+
key :active, Boolean, :default => true
|
624
|
+
key :smart, Boolean, :default => false
|
625
|
+
key :skills, Array, :default => [1]
|
626
|
+
key :options, Hash, :default => {'foo' => 'bar'}
|
627
|
+
end
|
628
|
+
|
629
|
+
@doc = @document.new
|
630
|
+
end
|
631
|
+
|
632
|
+
should "work for strings" do
|
633
|
+
@doc.name.should == 'foo'
|
634
|
+
end
|
635
|
+
|
636
|
+
should "work for integers" do
|
637
|
+
@doc.age.should == 20
|
638
|
+
end
|
639
|
+
|
640
|
+
should "work for floats" do
|
641
|
+
@doc.net_worth.should == 100.00
|
642
|
+
end
|
643
|
+
|
644
|
+
should "work for booleans" do
|
645
|
+
@doc.active.should == true
|
646
|
+
@doc.smart.should == false
|
647
|
+
end
|
648
|
+
|
649
|
+
should "work for arrays" do
|
650
|
+
@doc.skills.should == [1]
|
651
|
+
@doc.skills << 2
|
652
|
+
@doc.skills.should == [1, 2]
|
653
|
+
end
|
654
|
+
|
655
|
+
should "work for hashes" do
|
656
|
+
@doc.options['foo'].should == 'bar'
|
657
|
+
@doc.options['baz'] = 'wick'
|
658
|
+
@doc.options['baz'].should == 'wick'
|
659
|
+
end
|
660
|
+
end
|
661
|
+
end # instance of a embedded document
|
662
|
+
end
|
663
|
+
end
|