mongo_mapper 0.7.0 → 0.7.1
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 +3 -1
- data/Rakefile +9 -12
- data/lib/mongo_mapper.rb +30 -10
- data/lib/mongo_mapper/document.rb +16 -74
- data/lib/mongo_mapper/embedded_document.rb +7 -1
- data/lib/mongo_mapper/plugins.rb +3 -0
- data/lib/mongo_mapper/plugins/associations/embedded_collection.rb +1 -12
- data/lib/mongo_mapper/plugins/associations/in_array_proxy.rb +6 -1
- data/lib/mongo_mapper/plugins/associations/many_documents_proxy.rb +4 -1
- data/lib/mongo_mapper/plugins/callbacks.rb +183 -12
- data/lib/mongo_mapper/plugins/keys.rb +17 -5
- data/lib/mongo_mapper/plugins/modifiers.rb +87 -0
- data/lib/mongo_mapper/plugins/pagination/proxy.rb +7 -3
- data/lib/mongo_mapper/plugins/protected.rb +1 -1
- data/lib/mongo_mapper/plugins/rails.rb +16 -8
- data/lib/mongo_mapper/plugins/serialization.rb +51 -81
- data/lib/mongo_mapper/plugins/timestamps.rb +21 -0
- data/lib/mongo_mapper/plugins/userstamps.rb +14 -0
- data/lib/mongo_mapper/query.rb +1 -1
- data/lib/mongo_mapper/version.rb +3 -0
- data/mongo_mapper.gemspec +22 -11
- data/test/active_model_lint_test.rb +11 -0
- data/test/functional/associations/test_in_array_proxy.rb +16 -0
- data/test/functional/associations/test_many_documents_proxy.rb +22 -0
- data/test/functional/test_callbacks.rb +104 -34
- data/test/functional/test_document.rb +70 -149
- data/test/functional/test_embedded_document.rb +39 -34
- data/test/functional/test_indexing.rb +44 -0
- data/test/functional/test_modifiers.rb +297 -227
- data/test/functional/test_protected.rb +11 -5
- data/test/functional/test_timestamps.rb +64 -0
- data/test/functional/test_userstamps.rb +28 -0
- data/test/support/timing.rb +1 -1
- data/test/unit/serializers/test_json_serializer.rb +30 -17
- data/test/unit/test_embedded_document.rb +15 -15
- data/test/unit/test_keys.rb +15 -11
- data/test/unit/test_mongo_mapper.rb +31 -1
- data/test/unit/test_pagination.rb +33 -0
- data/test/unit/test_query.rb +6 -0
- data/test/unit/test_serialization.rb +3 -3
- data/test/unit/test_support.rb +9 -5
- metadata +17 -6
- data/VERSION +0 -1
@@ -16,7 +16,7 @@ class ProtectedTest < Test::Unit::TestCase
|
|
16
16
|
should 'have protected attributes class method' do
|
17
17
|
@doc_class.protected_attributes.should == [:admin].to_set
|
18
18
|
end
|
19
|
-
|
19
|
+
|
20
20
|
should "default protected attributes to nil" do
|
21
21
|
Doc().protected_attributes.should be_nil
|
22
22
|
end
|
@@ -46,7 +46,7 @@ class ProtectedTest < Test::Unit::TestCase
|
|
46
46
|
doc = @doc_class.new(:name => 'John')
|
47
47
|
doc.admin = true
|
48
48
|
doc.save!
|
49
|
-
|
49
|
+
|
50
50
|
doc = @doc_class.first(:name => 'John')
|
51
51
|
doc.admin.should be_true
|
52
52
|
doc.name.should == 'John'
|
@@ -63,8 +63,14 @@ class ProtectedTest < Test::Unit::TestCase
|
|
63
63
|
@doc.name.should == 'Stimpson J. Cat'
|
64
64
|
@doc.admin.should be_false
|
65
65
|
end
|
66
|
+
|
67
|
+
should 'be indifferent to whether the protected keys are strings or symbols' do
|
68
|
+
@doc.update_attributes!("name" => 'Stimpson J. Cat', "admin" => true)
|
69
|
+
@doc.name.should == 'Stimpson J. Cat'
|
70
|
+
@doc.admin.should be_false
|
71
|
+
end
|
66
72
|
end
|
67
|
-
|
73
|
+
|
68
74
|
context "Single collection inherited protected attributes" do
|
69
75
|
setup do
|
70
76
|
class ::GrandParent
|
@@ -126,7 +132,7 @@ class ProtectedTest < Test::Unit::TestCase
|
|
126
132
|
should 'have protected attributes class method' do
|
127
133
|
@edoc_class.protected_attributes.should == [:admin].to_set
|
128
134
|
end
|
129
|
-
|
135
|
+
|
130
136
|
should "default protected attributes to nil" do
|
131
137
|
EDoc().protected_attributes.should be_nil
|
132
138
|
end
|
@@ -152,4 +158,4 @@ class ProtectedTest < Test::Unit::TestCase
|
|
152
158
|
@edoc.admin.should be_false
|
153
159
|
end
|
154
160
|
end
|
155
|
-
end
|
161
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class TimestampsTest < Test::Unit::TestCase
|
4
|
+
context "timestamping" do
|
5
|
+
setup do
|
6
|
+
@klass = Doc do
|
7
|
+
set_collection_name 'users'
|
8
|
+
|
9
|
+
key :first_name, String
|
10
|
+
key :last_name, String
|
11
|
+
key :age, Integer
|
12
|
+
key :date, Date
|
13
|
+
end
|
14
|
+
@klass.timestamps!
|
15
|
+
end
|
16
|
+
|
17
|
+
should "set created_at and updated_at on create" do
|
18
|
+
doc = @klass.new(:first_name => 'John', :age => 27)
|
19
|
+
doc.created_at.should be(nil)
|
20
|
+
doc.updated_at.should be(nil)
|
21
|
+
doc.save
|
22
|
+
doc.created_at.should_not be(nil)
|
23
|
+
doc.updated_at.should_not be(nil)
|
24
|
+
end
|
25
|
+
|
26
|
+
should "not overwrite created_at if it already exists" do
|
27
|
+
original_created_at = 1.month.ago
|
28
|
+
doc = @klass.new(:first_name => 'John', :age => 27, :created_at => original_created_at)
|
29
|
+
doc.created_at.to_i.should == original_created_at.to_i
|
30
|
+
doc.updated_at.should be_nil
|
31
|
+
doc.save
|
32
|
+
doc.created_at.to_i.should == original_created_at.to_i
|
33
|
+
doc.updated_at.should_not be_nil
|
34
|
+
end
|
35
|
+
|
36
|
+
should "set updated_at on field update but leave created_at alone" do
|
37
|
+
doc = @klass.create(:first_name => 'John', :age => 27)
|
38
|
+
old_created_at = doc.created_at
|
39
|
+
old_updated_at = doc.updated_at
|
40
|
+
doc.first_name = 'Johnny'
|
41
|
+
|
42
|
+
Timecop.freeze(Time.now + 5.seconds) do
|
43
|
+
doc.save
|
44
|
+
end
|
45
|
+
|
46
|
+
doc.created_at.should == old_created_at
|
47
|
+
doc.updated_at.should_not == old_updated_at
|
48
|
+
end
|
49
|
+
|
50
|
+
should "set updated_at on document update but leave created_at alone" do
|
51
|
+
doc = @klass.create(:first_name => 'John', :age => 27)
|
52
|
+
old_created_at = doc.created_at
|
53
|
+
old_updated_at = doc.updated_at
|
54
|
+
|
55
|
+
Timecop.freeze(Time.now + 5.seconds) do
|
56
|
+
@klass.update(doc._id, { :first_name => 'Johnny' })
|
57
|
+
end
|
58
|
+
|
59
|
+
doc = doc.reload
|
60
|
+
doc.created_at.should == old_created_at
|
61
|
+
doc.updated_at.should_not == old_updated_at
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class UserstampsTest < Test::Unit::TestCase
|
4
|
+
context "userstamping" do
|
5
|
+
setup do
|
6
|
+
@document = Doc do
|
7
|
+
set_collection_name 'users'
|
8
|
+
userstamps!
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
should "add creator_id key" do
|
13
|
+
@document.keys.keys.should include('creator_id')
|
14
|
+
end
|
15
|
+
|
16
|
+
should "add updater_id key" do
|
17
|
+
@document.keys.keys.should include('updater_id')
|
18
|
+
end
|
19
|
+
|
20
|
+
should "add belongs_to creator" do
|
21
|
+
@document.associations.keys.should include('creator')
|
22
|
+
end
|
23
|
+
|
24
|
+
should "add belongs_to updater" do
|
25
|
+
@document.associations.keys.should include('updater')
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/test/support/timing.rb
CHANGED
@@ -1,6 +1,14 @@
|
|
1
1
|
require 'test_helper'
|
2
|
+
require 'active_support/version'
|
2
3
|
|
3
4
|
class JsonSerializationTest < Test::Unit::TestCase
|
5
|
+
|
6
|
+
# Helper function in case things change in the future
|
7
|
+
# - replacing all those to_json calls was a nightmare
|
8
|
+
def convert_to_json object, options = {}
|
9
|
+
ActiveSupport::JSON.encode(object, options)
|
10
|
+
end
|
11
|
+
|
4
12
|
class Tag
|
5
13
|
include MongoMapper::EmbeddedDocument
|
6
14
|
key :name, String
|
@@ -30,11 +38,11 @@ class JsonSerializationTest < Test::Unit::TestCase
|
|
30
38
|
|
31
39
|
should "include demodulized root" do
|
32
40
|
Contact.include_root_in_json = true
|
33
|
-
assert_match %r{^\{"contact"
|
41
|
+
assert_match %r{^\{"contact":\s?\{}, convert_to_json(@contact)
|
34
42
|
end
|
35
43
|
|
36
44
|
should "encode all encodable attributes" do
|
37
|
-
json = @contact
|
45
|
+
json = convert_to_json(@contact)
|
38
46
|
|
39
47
|
assert_no_match %r{"_id"}, json
|
40
48
|
assert_match %r{"name":"Konata Izumi"}, json
|
@@ -45,7 +53,7 @@ class JsonSerializationTest < Test::Unit::TestCase
|
|
45
53
|
end
|
46
54
|
|
47
55
|
should "allow attribute filtering with only" do
|
48
|
-
json = @contact
|
56
|
+
json = convert_to_json(@contact, :only => [:name, :age])
|
49
57
|
|
50
58
|
assert_no_match %r{"_id"}, json
|
51
59
|
assert_match %r{"name":"Konata Izumi"}, json
|
@@ -56,7 +64,7 @@ class JsonSerializationTest < Test::Unit::TestCase
|
|
56
64
|
end
|
57
65
|
|
58
66
|
should "allow attribute filtering with except" do
|
59
|
-
json = @contact
|
67
|
+
json = convert_to_json(@contact, :except => [:name, :age])
|
60
68
|
|
61
69
|
assert_no_match %r{"_id"}, json
|
62
70
|
assert_no_match %r{"name"}, json
|
@@ -68,12 +76,12 @@ class JsonSerializationTest < Test::Unit::TestCase
|
|
68
76
|
|
69
77
|
context "_id key" do
|
70
78
|
should "not be included by default" do
|
71
|
-
json = @contact
|
79
|
+
json = convert_to_json(@contact)
|
72
80
|
assert_no_match %r{"_id":}, json
|
73
81
|
end
|
74
82
|
|
75
83
|
should "not be included even if :except is used" do
|
76
|
-
json = @contact
|
84
|
+
json = convert_to_json(@contact, :except => :name)
|
77
85
|
assert_no_match %r{"_id":}, json
|
78
86
|
end
|
79
87
|
end
|
@@ -85,12 +93,12 @@ class JsonSerializationTest < Test::Unit::TestCase
|
|
85
93
|
end
|
86
94
|
|
87
95
|
should "be included by default" do
|
88
|
-
json = @contact
|
96
|
+
json = convert_to_json(@contact)
|
89
97
|
assert_match %r{"id"}, json
|
90
98
|
end
|
91
99
|
|
92
100
|
should "be included when single method included" do
|
93
|
-
json = @contact
|
101
|
+
json = convert_to_json(@contact, :methods => :label)
|
94
102
|
assert_match %r{"id"}, json
|
95
103
|
assert_match %r{"label":"Has cheezburger"}, json
|
96
104
|
assert_match %r{"name":"Konata Izumi"}, json
|
@@ -98,7 +106,7 @@ class JsonSerializationTest < Test::Unit::TestCase
|
|
98
106
|
end
|
99
107
|
|
100
108
|
should "be included when multiple methods included" do
|
101
|
-
json = @contact
|
109
|
+
json = convert_to_json(@contact, :methods => [:label, :favorite_quote])
|
102
110
|
assert_match %r{"id"}, json
|
103
111
|
assert_match %r{"label":"Has cheezburger"}, json
|
104
112
|
assert_match %r{"favorite_quote":"Constraints are liberating"}, json
|
@@ -106,9 +114,14 @@ class JsonSerializationTest < Test::Unit::TestCase
|
|
106
114
|
end
|
107
115
|
|
108
116
|
should "not be included if :only is present" do
|
109
|
-
json = @contact
|
117
|
+
json = convert_to_json(@contact, :only => :name)
|
110
118
|
assert_no_match %r{"id":}, json
|
111
119
|
end
|
120
|
+
|
121
|
+
should "be represented by a string" do
|
122
|
+
json = convert_to_json(@contact)
|
123
|
+
assert_match %r{"id":"}, json
|
124
|
+
end
|
112
125
|
end
|
113
126
|
|
114
127
|
context "including methods" do
|
@@ -118,12 +131,12 @@ class JsonSerializationTest < Test::Unit::TestCase
|
|
118
131
|
end
|
119
132
|
|
120
133
|
should "include single method" do
|
121
|
-
json = @contact
|
134
|
+
json = convert_to_json(@contact, :methods => :label)
|
122
135
|
assert_match %r{"label":"Has cheezburger"}, json
|
123
136
|
end
|
124
137
|
|
125
138
|
should "include multiple methods" do
|
126
|
-
json = @contact
|
139
|
+
json = convert_to_json(@contact, :only => :name, :methods => [:label, :favorite_quote])
|
127
140
|
assert_match %r{"label":"Has cheezburger"}, json
|
128
141
|
assert_match %r{"favorite_quote":"Constraints are liberating"}, json
|
129
142
|
assert_match %r{"name":"Konata Izumi"}, json
|
@@ -143,13 +156,13 @@ class JsonSerializationTest < Test::Unit::TestCase
|
|
143
156
|
end
|
144
157
|
|
145
158
|
should "allow attribute filtering with only" do
|
146
|
-
json =
|
159
|
+
json =convert_to_json(@contacts, :only => :name)
|
147
160
|
assert_match %r{\{"name":"David"\}}, json
|
148
161
|
assert_match %r{\{"name":"Mary"\}}, json
|
149
162
|
end
|
150
163
|
|
151
164
|
should "allow attribute filtering with except" do
|
152
|
-
json = @contacts
|
165
|
+
json = convert_to_json(@contacts, :except => [:name, :preferences, :awesome, :created_at, :updated_at])
|
153
166
|
assert_match %r{"age":39}, json
|
154
167
|
assert_match %r{"age":14}, json
|
155
168
|
assert_no_match %r{"name":}, json
|
@@ -165,7 +178,7 @@ class JsonSerializationTest < Test::Unit::TestCase
|
|
165
178
|
1 => Contact.new(:name => 'David', :age => 39),
|
166
179
|
2 => Contact.new(:name => 'Mary', :age => 14)
|
167
180
|
}
|
168
|
-
json = contacts
|
181
|
+
json = convert_to_json(contacts, :only => [1, :name])
|
169
182
|
assert_match %r{"1":}, json
|
170
183
|
assert_match %r{\{"name":"David"\}}, json
|
171
184
|
assert_no_match %r{"2":}, json
|
@@ -174,7 +187,7 @@ class JsonSerializationTest < Test::Unit::TestCase
|
|
174
187
|
should "include embedded attributes" do
|
175
188
|
contact = Contact.new(:name => 'John', :age => 27)
|
176
189
|
contact.tags = [Tag.new(:name => 'awesome'), Tag.new(:name => 'ruby')]
|
177
|
-
json = contact
|
190
|
+
json = convert_to_json(contact)
|
178
191
|
assert_match %r{"tags":}, json
|
179
192
|
assert_match %r{"name":"awesome"}, json
|
180
193
|
assert_match %r{"name":"ruby"}, json
|
@@ -183,7 +196,7 @@ class JsonSerializationTest < Test::Unit::TestCase
|
|
183
196
|
should "include dynamic attributes" do
|
184
197
|
contact = Contact.new(:name => 'John', :age => 27, :foo => 'bar')
|
185
198
|
contact['smell'] = 'stinky'
|
186
|
-
json = contact
|
199
|
+
json = convert_to_json(contact)
|
187
200
|
assert_match %r{"smell":"stinky"}, json
|
188
201
|
end
|
189
202
|
end
|
@@ -42,7 +42,7 @@ class EmbeddedDocumentTest < Test::Unit::TestCase
|
|
42
42
|
Object.send :remove_const, 'Child' if defined?(::Child)
|
43
43
|
Object.send :remove_const, 'OtherChild' if defined?(::OtherChild)
|
44
44
|
end
|
45
|
-
|
45
|
+
|
46
46
|
context "Including MongoMapper::EmbeddedDocument in a class" do
|
47
47
|
setup do
|
48
48
|
@klass = EDoc()
|
@@ -249,34 +249,34 @@ class EmbeddedDocumentTest < Test::Unit::TestCase
|
|
249
249
|
|
250
250
|
should "convert string object id to mongo object id when assigning id with _id object id type" do
|
251
251
|
id = Mongo::ObjectID.new
|
252
|
-
|
253
252
|
doc = @document.new(:id => id.to_s)
|
254
253
|
doc._id.should == id
|
255
|
-
doc.id.should
|
256
|
-
|
254
|
+
doc.id.should == id
|
257
255
|
doc = @document.new(:_id => id.to_s)
|
258
256
|
doc._id.should == id
|
259
|
-
doc.id.should
|
257
|
+
doc.id.should == id
|
260
258
|
end
|
261
259
|
|
262
|
-
context "
|
260
|
+
context "_parent_document" do
|
263
261
|
should "default to nil" do
|
262
|
+
@document.new._parent_document.should be_nil
|
264
263
|
@document.new._root_document.should be_nil
|
265
264
|
end
|
266
265
|
|
267
|
-
should "
|
266
|
+
should "set _root_document when setting _parent_document" do
|
268
267
|
root = Doc().new
|
269
|
-
doc = @document.new
|
270
|
-
|
268
|
+
doc = @document.new(:_parent_document => root)
|
269
|
+
doc._parent_document.should be(root)
|
271
270
|
doc._root_document.should be(root)
|
272
271
|
end
|
273
272
|
|
274
|
-
should "
|
275
|
-
root
|
276
|
-
klass
|
277
|
-
|
278
|
-
|
279
|
-
|
273
|
+
should "set _root_document when setting _parent_document on embedded many" do
|
274
|
+
root = Doc().new
|
275
|
+
klass = EDoc { many :children }
|
276
|
+
parent = klass.new(:_parent_document => root, :children => [{}])
|
277
|
+
child = parent.children.first
|
278
|
+
child._parent_document.should be(parent)
|
279
|
+
child._root_document.should be(root)
|
280
280
|
end
|
281
281
|
end
|
282
282
|
|
data/test/unit/test_keys.rb
CHANGED
@@ -42,25 +42,25 @@ class KeyTest < Test::Unit::TestCase
|
|
42
42
|
should "symbolize option keys" do
|
43
43
|
Key.new(:foo, Integer, 'required' => true).options[:required].should be(true)
|
44
44
|
end
|
45
|
-
|
45
|
+
|
46
46
|
should "work with just name" do
|
47
47
|
key = Key.new(:foo)
|
48
48
|
key.name.should == 'foo'
|
49
49
|
end
|
50
|
-
|
50
|
+
|
51
51
|
should "work with name and type" do
|
52
52
|
key = Key.new(:foo, String)
|
53
53
|
key.name.should == 'foo'
|
54
54
|
key.type.should == String
|
55
55
|
end
|
56
|
-
|
56
|
+
|
57
57
|
should "work with name, type, and options" do
|
58
58
|
key = Key.new(:foo, String, :required => true)
|
59
59
|
key.name.should == 'foo'
|
60
60
|
key.type.should == String
|
61
61
|
key.options[:required].should be_true
|
62
62
|
end
|
63
|
-
|
63
|
+
|
64
64
|
should "work with name and options" do
|
65
65
|
key = Key.new(:foo, :required => true)
|
66
66
|
key.name.should == 'foo'
|
@@ -80,7 +80,7 @@ class KeyTest < Test::Unit::TestCase
|
|
80
80
|
should "not be equal to another key with different type" do
|
81
81
|
Key.new(:name, String).should_not == Key.new(:name, Integer)
|
82
82
|
end
|
83
|
-
|
83
|
+
|
84
84
|
should "know if it is a embedded_document" do
|
85
85
|
Key.new(:name, EDoc()).embeddable?.should be_true
|
86
86
|
end
|
@@ -88,12 +88,12 @@ class KeyTest < Test::Unit::TestCase
|
|
88
88
|
should "know if it is not a embedded_document" do
|
89
89
|
Key.new(:name, String).embeddable?.should be_false
|
90
90
|
end
|
91
|
-
|
91
|
+
|
92
92
|
should "know if it is a number" do
|
93
93
|
Key.new(:age, Integer).number?.should be_true
|
94
94
|
Key.new(:age, Float).number?.should be_true
|
95
95
|
end
|
96
|
-
|
96
|
+
|
97
97
|
should "know if it is not a number" do
|
98
98
|
Key.new(:age, String).number?.should be_false
|
99
99
|
end
|
@@ -110,7 +110,7 @@ class KeyTest < Test::Unit::TestCase
|
|
110
110
|
key.set(FooType.new('something')).should == 'to_mongo'
|
111
111
|
end
|
112
112
|
end
|
113
|
-
|
113
|
+
|
114
114
|
context "getting a value with a custom type" do
|
115
115
|
should "use #from_mongo to convert back to custom type" do
|
116
116
|
key = Key.new(:foo, FooType)
|
@@ -123,7 +123,7 @@ class KeyTest < Test::Unit::TestCase
|
|
123
123
|
key = Key.new(:foo, String)
|
124
124
|
key.get('bar').should == 'bar'
|
125
125
|
end
|
126
|
-
|
126
|
+
|
127
127
|
should "work without type" do
|
128
128
|
key = Key.new(:foo)
|
129
129
|
key.get([1, '2']).should == [1, '2']
|
@@ -144,7 +144,7 @@ class KeyTest < Test::Unit::TestCase
|
|
144
144
|
end
|
145
145
|
end
|
146
146
|
end
|
147
|
-
|
147
|
+
|
148
148
|
context "getting a value with a default set" do
|
149
149
|
setup do
|
150
150
|
@key = Key.new(:foo, String, :default => 'baz')
|
@@ -157,7 +157,7 @@ class KeyTest < Test::Unit::TestCase
|
|
157
157
|
should "return value if not blank" do
|
158
158
|
@key.get('foobar').should == 'foobar'
|
159
159
|
end
|
160
|
-
|
160
|
+
|
161
161
|
should "work with Boolean type and false value" do
|
162
162
|
Key.new(:active, Boolean, :default => false).get(nil).should be_false
|
163
163
|
end
|
@@ -165,5 +165,9 @@ class KeyTest < Test::Unit::TestCase
|
|
165
165
|
should "work with Boolean type and true value" do
|
166
166
|
Key.new(:active, Boolean, :default => true).get(nil).should be_true
|
167
167
|
end
|
168
|
+
|
169
|
+
should "work with procs" do
|
170
|
+
Key.new(:foo, String, :default => lambda { return 'hello world' }).get(nil).should == "hello world"
|
171
|
+
end
|
168
172
|
end
|
169
173
|
end # KeyTest
|