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