mongomatic 0.3.2 → 0.4.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/lib/mongomatic/expectations/expected.rb +16 -2
- data/lib/mongomatic/expectations.rb +1 -1
- data/lib/mongomatic/modifiers.rb +225 -42
- data/test/test_modifiers.rb +253 -0
- data/test/test_mongomatic.rb +54 -0
- metadata +6 -4
@@ -6,11 +6,25 @@ module Mongomatic
|
|
6
6
|
end
|
7
7
|
|
8
8
|
def to_be
|
9
|
-
|
9
|
+
case value
|
10
|
+
when Proc
|
11
|
+
add_error_msg unless value.call
|
12
|
+
when Symbol
|
13
|
+
add_error_msg unless instance.send(value)
|
14
|
+
else
|
15
|
+
add_error_msg unless value
|
16
|
+
end
|
10
17
|
end
|
11
18
|
|
12
19
|
def to_not_be
|
13
|
-
|
20
|
+
case value
|
21
|
+
when Proc
|
22
|
+
add_error_msg if value.call
|
23
|
+
when Symbol
|
24
|
+
add_error_msg if instance.send(value)
|
25
|
+
else
|
26
|
+
add_error_msg if value
|
27
|
+
end
|
14
28
|
end
|
15
29
|
end
|
16
30
|
end
|
data/lib/mongomatic/modifiers.rb
CHANGED
@@ -2,15 +2,46 @@ module Mongomatic
|
|
2
2
|
# Provides convenience methods for atomic MongoDB operations.
|
3
3
|
module Modifiers
|
4
4
|
|
5
|
+
class UnexpectedFieldType < RuntimeError; end
|
6
|
+
|
7
|
+
def hash_for_field(field)
|
8
|
+
parts = field.split(".")
|
9
|
+
return [parts[0], self.doc] if parts.size == 1
|
10
|
+
field = parts.pop # last one is the field
|
11
|
+
curr_hash = self.doc
|
12
|
+
parts.each_with_index do |part, i|
|
13
|
+
curr_hash[part] ||= {}
|
14
|
+
return [field, curr_hash[part]] if parts.size == i+1
|
15
|
+
curr_hash = curr_hash[part]
|
16
|
+
end
|
17
|
+
end
|
18
|
+
private :hash_for_field
|
19
|
+
|
5
20
|
# MongoDB equivalent: { $push : { field : value } }<br/>
|
6
21
|
# Appends value to field, if field is an existing array, otherwise sets field to the array [value]
|
7
|
-
# if field is not present. If field is present but is not an array,
|
8
|
-
|
9
|
-
|
10
|
-
field =
|
11
|
-
|
12
|
-
|
22
|
+
# if field is not present. If field is present but is not an array, error is returned.
|
23
|
+
def push(field, val, safe=false)
|
24
|
+
mongo_field = field.to_s
|
25
|
+
field, hash = hash_for_field(mongo_field)
|
26
|
+
|
27
|
+
unless hash[field].nil? || hash[field].is_a?(Array)
|
28
|
+
raise(UnexpectedFieldType)
|
13
29
|
end
|
30
|
+
|
31
|
+
op = { "$push" => { mongo_field => val } }
|
32
|
+
res = true
|
33
|
+
|
34
|
+
safe == true ? res = update!({}, op) : update({}, op)
|
35
|
+
|
36
|
+
if res
|
37
|
+
hash[field] ||= []
|
38
|
+
hash[field] << val
|
39
|
+
true
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def push!(field, val)
|
44
|
+
push(field, val, true)
|
14
45
|
end
|
15
46
|
|
16
47
|
# MongoDB equivalent: { $pushAll : { field : value_array } }<br/>
|
@@ -18,97 +49,249 @@ module Mongomatic
|
|
18
49
|
# the array value_array if field is not present. If field is present but is not an array, an error
|
19
50
|
# condition is raised.
|
20
51
|
# user.push("interests", ["skydiving", "coding"])
|
21
|
-
def push_all(field, val,
|
22
|
-
|
52
|
+
def push_all(field, val, safe=false)
|
53
|
+
mongo_field = field.to_s
|
54
|
+
field, hash = hash_for_field(mongo_field)
|
55
|
+
|
56
|
+
unless hash[field].nil? || hash[field].is_a?(Array)
|
57
|
+
raise(UnexpectedFieldType)
|
58
|
+
end
|
59
|
+
|
23
60
|
val = Array(val)
|
24
|
-
|
25
|
-
|
61
|
+
op = { "$pushAll" => { mongo_field => val } }
|
62
|
+
res = true
|
63
|
+
|
64
|
+
safe == true ? res = update!({}, op) : update({}, op)
|
65
|
+
|
66
|
+
if res
|
67
|
+
hash[field] ||= []
|
68
|
+
val.each { |v| hash[field] << v }
|
69
|
+
true
|
26
70
|
end
|
27
71
|
end
|
28
72
|
|
73
|
+
def push_all!(field, val)
|
74
|
+
push_all(field, val, true)
|
75
|
+
end
|
76
|
+
|
29
77
|
# MongoDB equivalent: { $pull : { field : _value } }<br/>
|
30
78
|
# Removes all occurrences of value from field, if field is an array. If field is present but is not
|
31
79
|
# an array, an error condition is raised.
|
32
80
|
# user.pull("interests", "watching paint dry")
|
33
|
-
def pull(field, val,
|
34
|
-
|
35
|
-
|
36
|
-
|
81
|
+
def pull(field, val, safe=false)
|
82
|
+
mongo_field = field.to_s
|
83
|
+
field, hash = hash_for_field(mongo_field)
|
84
|
+
|
85
|
+
unless hash[field].nil? || hash[field].is_a?(Array)
|
86
|
+
raise(UnexpectedFieldType)
|
87
|
+
end
|
88
|
+
|
89
|
+
op = { "$pull" => { mongo_field => val } }
|
90
|
+
res = true
|
91
|
+
|
92
|
+
safe == true ? res = update!({}, op) : update({}, op)
|
93
|
+
|
94
|
+
if res
|
95
|
+
hash[field] ||= []
|
96
|
+
hash[field].delete(val)
|
97
|
+
true
|
37
98
|
end
|
38
99
|
end
|
39
100
|
|
101
|
+
def pull!(field, val)
|
102
|
+
pull(field, val, true)
|
103
|
+
end
|
104
|
+
|
40
105
|
# MongoDB equivalent: { $pullAll : { field : value_array } }<br/>
|
41
106
|
# Removes all occurrences of each value in value_array from field, if field is an array. If field is
|
42
107
|
# present but is not an array, an error condition is raised.
|
43
108
|
# user.pull_all("interests", ["watching paint dry", "sitting on my ass"])
|
44
|
-
def pull_all(field, val,
|
45
|
-
|
46
|
-
|
47
|
-
|
109
|
+
def pull_all(field, val, safe=false)
|
110
|
+
mongo_field = field.to_s
|
111
|
+
field, hash = hash_for_field(mongo_field)
|
112
|
+
|
113
|
+
unless hash[field].nil? || hash[field].is_a?(Array)
|
114
|
+
raise(UnexpectedFieldType)
|
48
115
|
end
|
116
|
+
|
117
|
+
op = { "$pullAll" => { mongo_field => Array(val) } }
|
118
|
+
res = true
|
119
|
+
|
120
|
+
safe == true ? res = update!({}, op) : update({}, op)
|
121
|
+
|
122
|
+
if res
|
123
|
+
hash[field] ||= []
|
124
|
+
Array(val).each do |v|
|
125
|
+
hash[field].delete(v)
|
126
|
+
end; true
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def pull_all!(field, val)
|
131
|
+
pull_all(field, val, true)
|
49
132
|
end
|
50
133
|
|
51
134
|
# MongoDB equivalent: { $inc : { field : value } }<br/>
|
52
135
|
# Increments field by the number value if field is present in the object, otherwise sets field to the number value.
|
53
136
|
# user.inc("cents_in_wallet", 1000)
|
54
|
-
def inc(field, val,
|
55
|
-
|
56
|
-
|
57
|
-
|
137
|
+
def inc(field, val, safe=false)
|
138
|
+
mongo_field = field.to_s
|
139
|
+
field, hash = hash_for_field(mongo_field)
|
140
|
+
|
141
|
+
unless hash[field].nil? || ["Fixnum","Float"].include?(hash[field].class.to_s)
|
142
|
+
raise(UnexpectedFieldType)
|
143
|
+
end
|
144
|
+
|
145
|
+
op = { "$inc" => { mongo_field => val } }
|
146
|
+
res = true
|
147
|
+
|
148
|
+
safe == true ? res = update!({}, op) : update({}, op)
|
149
|
+
|
150
|
+
if res
|
151
|
+
hash[field] ||= 0
|
152
|
+
hash[field] += val
|
153
|
+
true
|
58
154
|
end
|
59
155
|
end
|
60
156
|
|
157
|
+
def inc!(field, val)
|
158
|
+
inc(field, val, true)
|
159
|
+
end
|
160
|
+
|
61
161
|
# MongoDB equivalent: { $set : { field : value } }<br/>
|
62
162
|
# Sets field to value. All datatypes are supported with $set.
|
63
163
|
# user.set("name", "Ben")
|
64
|
-
def set(field, val,
|
65
|
-
|
66
|
-
|
67
|
-
|
164
|
+
def set(field, val, safe=false)
|
165
|
+
mongo_field = field.to_s
|
166
|
+
field, hash = hash_for_field(field.to_s)
|
167
|
+
|
168
|
+
op = { "$set" => { mongo_field => val } }
|
169
|
+
res = true
|
170
|
+
|
171
|
+
safe == true ? res = update!({}, op) : update({}, op)
|
172
|
+
|
173
|
+
if res
|
174
|
+
hash[field] = val
|
175
|
+
true
|
68
176
|
end
|
69
177
|
end
|
178
|
+
|
179
|
+
def set!(field, val)
|
180
|
+
set(field, val, true)
|
181
|
+
end
|
70
182
|
|
71
183
|
# MongoDB equivalent: { $unset : { field : 1} }<br/>
|
72
184
|
# Deletes a given field. v1.3+
|
73
185
|
# user.unset("name")
|
74
|
-
def unset(field,
|
75
|
-
|
76
|
-
|
77
|
-
|
186
|
+
def unset(field, safe=false)
|
187
|
+
mongo_field = field.to_s
|
188
|
+
field, hash = hash_for_field(mongo_field)
|
189
|
+
|
190
|
+
op = { "$unset" => { mongo_field => 1 } }
|
191
|
+
res = true
|
192
|
+
|
193
|
+
safe == true ? res = update!({}, op) : update({}, op)
|
194
|
+
|
195
|
+
if res
|
196
|
+
hash.delete(field)
|
197
|
+
true
|
78
198
|
end
|
79
199
|
end
|
80
200
|
|
201
|
+
def unset!(field)
|
202
|
+
unset(field, true)
|
203
|
+
end
|
204
|
+
|
81
205
|
# MongoDB equivalent: { $addToSet : { field : value } }<br/>
|
82
206
|
# Adds value to the array only if its not in the array already.<br/>
|
83
207
|
# Or to add many values:<br/>
|
84
208
|
# { $addToSet : { a : { $each : [ 3 , 5 , 6 ] } } }
|
85
209
|
# user.add_to_set("friend_ids", BSON::ObjectID('...'))
|
86
|
-
def add_to_set(field, val,
|
87
|
-
|
88
|
-
|
89
|
-
|
210
|
+
def add_to_set(field, val, safe=false)
|
211
|
+
mongo_field = field.to_s
|
212
|
+
field, hash = hash_for_field(mongo_field)
|
213
|
+
|
214
|
+
unless hash[field].nil? || hash[field].is_a?(Array)
|
215
|
+
raise(UnexpectedFieldType)
|
216
|
+
end
|
217
|
+
|
218
|
+
return false if val.nil?
|
219
|
+
|
220
|
+
if val.is_a?(Array)
|
221
|
+
op = { "$addToSet" => { mongo_field => { "$each" => val } } }
|
222
|
+
else
|
223
|
+
op = { "$addToSet" => { mongo_field => val } }
|
224
|
+
end
|
225
|
+
|
226
|
+
res = true
|
227
|
+
safe == true ? res = update!({}, op) : update({}, op)
|
228
|
+
|
229
|
+
if res
|
230
|
+
hash[field] ||= []
|
231
|
+
Array(val).each do |v|
|
232
|
+
hash[field] << v unless hash[field].include?(v)
|
233
|
+
end
|
234
|
+
true
|
90
235
|
end
|
91
236
|
end
|
92
237
|
|
238
|
+
def add_to_set!(field, val)
|
239
|
+
add_to_set(field, val, true)
|
240
|
+
end
|
241
|
+
|
93
242
|
# MongoDB equivalent: { $pop : { field : 1 } }<br/>
|
94
243
|
# Removes the last element in an array (ADDED in 1.1)
|
95
244
|
# user.pop_last("friend_ids")
|
96
|
-
def pop_last(field,
|
97
|
-
|
98
|
-
|
99
|
-
|
245
|
+
def pop_last(field, safe=false)
|
246
|
+
mongo_field = field.to_s
|
247
|
+
field, hash = hash_for_field(mongo_field)
|
248
|
+
|
249
|
+
unless hash[field].nil? || hash[field].is_a?(Array)
|
250
|
+
raise(UnexpectedFieldType)
|
100
251
|
end
|
252
|
+
|
253
|
+
op = { "$pop" => { mongo_field => 1 } }
|
254
|
+
|
255
|
+
res = true
|
256
|
+
safe == true ? res = update!({}, op) : update({}, op)
|
257
|
+
|
258
|
+
if res
|
259
|
+
hash[field] ||= []
|
260
|
+
hash[field].pop
|
261
|
+
true
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
def pop_last!(field)
|
266
|
+
pop_last(field, true)
|
101
267
|
end
|
102
268
|
|
103
269
|
# MongoDB equivalent: { $pop : { field : -1 } }<br/>
|
104
270
|
# Removes the first element in an array (ADDED in 1.1)
|
105
271
|
# user.pop_first("friend_ids")
|
106
|
-
def pop_first(field,
|
107
|
-
|
108
|
-
|
109
|
-
|
272
|
+
def pop_first(field, safe=false)
|
273
|
+
mongo_field = field.to_s
|
274
|
+
field, hash = hash_for_field(mongo_field)
|
275
|
+
|
276
|
+
unless hash[field].nil? || hash[field].is_a?(Array)
|
277
|
+
raise(UnexpectedFieldType)
|
278
|
+
end
|
279
|
+
|
280
|
+
op = { "$pop" => { mongo_field => -1 } }
|
281
|
+
|
282
|
+
res = true
|
283
|
+
safe == true ? res = update!({}, op) : update({}, op)
|
284
|
+
|
285
|
+
if res
|
286
|
+
hash[field] ||= []
|
287
|
+
hash[field].shift
|
288
|
+
true
|
110
289
|
end
|
111
290
|
end
|
112
291
|
|
292
|
+
def pop_first!(field)
|
293
|
+
pop_first(field, true)
|
294
|
+
end
|
295
|
+
|
113
296
|
end
|
114
297
|
end
|
@@ -0,0 +1,253 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestModifiers < Test::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
Person.collection.drop
|
6
|
+
end
|
7
|
+
|
8
|
+
should "be able to push" do
|
9
|
+
p1 = Person.new(:name => "Jordan")
|
10
|
+
p1.insert
|
11
|
+
assert p1.push("interests", "skydiving")
|
12
|
+
assert p1["interests"].include?("skydiving")
|
13
|
+
p1 = Person.find_one(p1["_id"])
|
14
|
+
assert p1["interests"].include?("skydiving")
|
15
|
+
assert p1.push!("interests", "coding")
|
16
|
+
assert p1["interests"].include?("coding")
|
17
|
+
p1 = Person.find_one(p1["_id"])
|
18
|
+
assert_equal ["skydiving","coding"], p1["interests"]
|
19
|
+
|
20
|
+
p1["interests"] = "foo"
|
21
|
+
assert_raise(Mongomatic::Modifiers::UnexpectedFieldType) { p1.push("interests", "snowboarding") }
|
22
|
+
end
|
23
|
+
|
24
|
+
should "be able to push on a field in an embedded hash" do
|
25
|
+
p1 = Person.new(:name => "Jordan")
|
26
|
+
p1.insert
|
27
|
+
assert p1.push!("personal.interests", "skydiving")
|
28
|
+
assert_equal ["skydiving"], p1["personal"]["interests"]
|
29
|
+
p1 = Person.find_one(p1["_id"])
|
30
|
+
assert_equal ["skydiving"], p1["personal"]["interests"]
|
31
|
+
end
|
32
|
+
|
33
|
+
should "be able to push_all" do
|
34
|
+
p1 = Person.new(:name => "Jordan")
|
35
|
+
p1.insert
|
36
|
+
assert p1.push("interests", "skydiving")
|
37
|
+
assert p1["interests"].include?("skydiving")
|
38
|
+
p1 = Person.find_one(p1["_id"])
|
39
|
+
assert p1["interests"].include?("skydiving")
|
40
|
+
|
41
|
+
assert p1.push_all!("interests", ["coding","running","snowboarding","reading"])
|
42
|
+
assert_equal ["skydiving","coding","running","snowboarding","reading"], p1["interests"]
|
43
|
+
p1 = Person.find_one(p1["_id"])
|
44
|
+
assert_equal ["skydiving","coding","running","snowboarding","reading"], p1["interests"]
|
45
|
+
|
46
|
+
p1["interests"] = "foo"
|
47
|
+
assert_raise(Mongomatic::Modifiers::UnexpectedFieldType) { p1.push_all("interests", ["snowboarding"]) }
|
48
|
+
end
|
49
|
+
|
50
|
+
should "be able to push_all on a field in an embedded hash" do
|
51
|
+
p1 = Person.new(:name => "Jordan")
|
52
|
+
p1.insert
|
53
|
+
p1.push_all!("contacts.coworkers", ["Chris","Keith","Jordan","Mike"])
|
54
|
+
assert_equal ["Chris","Keith","Jordan","Mike"], p1["contacts"]["coworkers"]
|
55
|
+
p1 = Person.find_one(p1["_id"])
|
56
|
+
assert_equal ["Chris","Keith","Jordan","Mike"], p1["contacts"]["coworkers"]
|
57
|
+
end
|
58
|
+
|
59
|
+
should "be able to pull" do
|
60
|
+
p1 = Person.new(:name => "Jordan")
|
61
|
+
p1.insert
|
62
|
+
assert p1.push("interests", "skydiving")
|
63
|
+
assert p1.push_all!("interests", ["coding","running","snowboarding","reading"])
|
64
|
+
p1 = Person.find_one(p1["_id"])
|
65
|
+
assert_equal ["skydiving","coding","running","snowboarding","reading"], p1["interests"]
|
66
|
+
assert p1.pull!("interests", "running")
|
67
|
+
assert_equal ["skydiving","coding","snowboarding","reading"], p1["interests"]
|
68
|
+
p1 = Person.find_one(p1["_id"])
|
69
|
+
assert_equal ["skydiving","coding","snowboarding","reading"], p1["interests"]
|
70
|
+
|
71
|
+
p1["interests"] = "foo"
|
72
|
+
assert_raise(Mongomatic::Modifiers::UnexpectedFieldType) { p1.pull("interests", ["snowboarding"]) }
|
73
|
+
end
|
74
|
+
|
75
|
+
should "be able to pull on a field in an embedded hash" do
|
76
|
+
p1 = Person.new(:name => "Jordan")
|
77
|
+
p1.insert!
|
78
|
+
p1.push_all!("contacts.coworkers", ["Chris","Keith","Jordan","Mike","Joe"])
|
79
|
+
assert_equal ["Chris","Keith","Jordan","Mike","Joe"], p1["contacts"]["coworkers"]
|
80
|
+
p1.pull!("contacts.coworkers", "Joe")
|
81
|
+
assert_equal ["Chris","Keith","Jordan","Mike"], p1["contacts"]["coworkers"]
|
82
|
+
p1 = Person.find_one(p1["_id"])
|
83
|
+
assert_equal ["Chris","Keith","Jordan","Mike"], p1["contacts"]["coworkers"]
|
84
|
+
end
|
85
|
+
|
86
|
+
should "be able to pull_all" do
|
87
|
+
p1 = Person.new(:name => "Jordan")
|
88
|
+
p1.insert
|
89
|
+
assert p1.push_all!("interests", ["skydiving", "coding","running","snowboarding","reading"])
|
90
|
+
p1 = Person.find_one(p1["_id"])
|
91
|
+
assert_equal ["skydiving","coding","running","snowboarding","reading"], p1["interests"]
|
92
|
+
p1.pull_all!("interests", ["running", "snowboarding"])
|
93
|
+
assert_equal ["skydiving", "coding","reading"], p1["interests"]
|
94
|
+
p1 = Person.find_one(p1["_id"])
|
95
|
+
assert_equal ["skydiving", "coding","reading"], p1["interests"]
|
96
|
+
|
97
|
+
p1["interests"] = "foo"
|
98
|
+
assert_raise(Mongomatic::Modifiers::UnexpectedFieldType) { p1.pull_all("interests", ["snowboarding"]) }
|
99
|
+
end
|
100
|
+
|
101
|
+
should "be able to pull_all on a field in an embedded hash" do
|
102
|
+
p1 = Person.new(:name => "Jordan")
|
103
|
+
p1.insert!
|
104
|
+
p1.push_all!("contacts.coworkers", ["Chris","Jim","Keith","Jordan","Mike","Joe"])
|
105
|
+
assert_equal ["Chris","Jim","Keith","Jordan","Mike","Joe"], p1["contacts"]["coworkers"]
|
106
|
+
p1.pull_all!("contacts.coworkers", ["Joe","Jim"])
|
107
|
+
assert_equal ["Chris","Keith","Jordan","Mike"], p1["contacts"]["coworkers"]
|
108
|
+
p1 = Person.find_one(p1["_id"])
|
109
|
+
assert_equal ["Chris","Keith","Jordan","Mike"], p1["contacts"]["coworkers"]
|
110
|
+
end
|
111
|
+
|
112
|
+
should "be able to inc" do
|
113
|
+
p1 = Person.new(:name => "Jordan")
|
114
|
+
assert p1.insert!
|
115
|
+
p1["count1"] = 5
|
116
|
+
assert p1.update!
|
117
|
+
assert p1.inc!("count1", 3)
|
118
|
+
assert p1.inc!("count2", -4)
|
119
|
+
assert_equal 8, p1["count1"]
|
120
|
+
assert_equal -4, p1["count2"]
|
121
|
+
p1 = Person.find_one(p1["_id"])
|
122
|
+
assert_equal 8, p1["count1"]
|
123
|
+
assert_equal -4, p1["count2"]
|
124
|
+
end
|
125
|
+
|
126
|
+
should "be able to inc a field in an embedded hash" do
|
127
|
+
p1 = Person.new(:name => "Jordan")
|
128
|
+
assert p1.insert!
|
129
|
+
p1.inc!("counters.visitors", 10)
|
130
|
+
p1.inc!("level1.level2.level3.counter", 20)
|
131
|
+
assert_equal 10, p1["counters"]["visitors"]
|
132
|
+
assert_equal 20, p1["level1"]["level2"]["level3"]["counter"]
|
133
|
+
p1 = Person.find_one(p1["_id"])
|
134
|
+
assert_equal 10, p1["counters"]["visitors"]
|
135
|
+
assert_equal 20, p1["level1"]["level2"]["level3"]["counter"]
|
136
|
+
end
|
137
|
+
|
138
|
+
should "be able to set" do
|
139
|
+
p1 = Person.new(:name => "Jordan")
|
140
|
+
assert p1.insert!
|
141
|
+
assert p1.set!("foo", "bar")
|
142
|
+
assert_equal "bar", p1["foo"]
|
143
|
+
p1 = Person.find_one(p1["_id"])
|
144
|
+
assert_equal "bar", p1["foo"]
|
145
|
+
end
|
146
|
+
|
147
|
+
should "be able to set a field in an embedded hash" do
|
148
|
+
p1 = Person.new(:name => "Jordan")
|
149
|
+
assert p1.insert!
|
150
|
+
p1.set!("l1.l2.l3.l4.name", "Ben")
|
151
|
+
assert_equal "Ben", p1["l1"]["l2"]["l3"]["l4"]["name"]
|
152
|
+
p1 = Person.find_one(p1["_id"])
|
153
|
+
assert_equal "Ben", p1["l1"]["l2"]["l3"]["l4"]["name"]
|
154
|
+
end
|
155
|
+
|
156
|
+
should "be able to unset" do
|
157
|
+
p1 = Person.new(:name => "Jordan")
|
158
|
+
assert p1.insert!
|
159
|
+
assert p1.set!("foo", "bar")
|
160
|
+
assert_equal "bar", p1["foo"]
|
161
|
+
p1 = Person.find_one(p1["_id"])
|
162
|
+
assert_equal "bar", p1["foo"]
|
163
|
+
|
164
|
+
assert p1.unset!("foo")
|
165
|
+
assert p1["foo"].nil?
|
166
|
+
p1 = Person.find_one(p1["_id"])
|
167
|
+
assert p1["foo"].nil?
|
168
|
+
end
|
169
|
+
|
170
|
+
should "be able to unset a field in an embedded hash" do
|
171
|
+
p1 = Person.new(:name => "Jordan")
|
172
|
+
assert p1.insert!
|
173
|
+
p1.set!("l1.l2.l3.l4.name", "Ben")
|
174
|
+
assert_equal "Ben", p1["l1"]["l2"]["l3"]["l4"]["name"]
|
175
|
+
p1 = Person.find_one(p1["_id"])
|
176
|
+
assert_equal "Ben", p1["l1"]["l2"]["l3"]["l4"]["name"]
|
177
|
+
assert p1["l1"]["l2"]["l3"]["l4"].has_key?("name")
|
178
|
+
|
179
|
+
p1.unset!("l1.l2.l3.l4.name")
|
180
|
+
assert_equal nil, p1["l1"]["l2"]["l3"]["l4"]["name"]
|
181
|
+
assert !p1["l1"]["l2"]["l3"]["l4"].has_key?("name")
|
182
|
+
|
183
|
+
p1 = Person.find_one(p1["_id"])
|
184
|
+
assert_equal nil, p1["l1"]["l2"]["l3"]["l4"]["name"]
|
185
|
+
assert !p1["l1"]["l2"]["l3"]["l4"].has_key?("name")
|
186
|
+
end
|
187
|
+
|
188
|
+
should "be able to add_to_set" do
|
189
|
+
p1 = Person.new(:name => "Jordan")
|
190
|
+
assert p1.insert!
|
191
|
+
|
192
|
+
assert p1.add_to_set!("hot_colors", "red")
|
193
|
+
assert p1.add_to_set!("cold_colors", ["grey","blue"])
|
194
|
+
|
195
|
+
assert_equal ["red"], p1["hot_colors"]
|
196
|
+
assert_equal ["grey","blue"], p1["cold_colors"]
|
197
|
+
|
198
|
+
p1 = Person.find_one(p1["_id"])
|
199
|
+
|
200
|
+
assert_equal ["red"], p1["hot_colors"]
|
201
|
+
assert_equal ["grey","blue"], p1["cold_colors"]
|
202
|
+
end
|
203
|
+
|
204
|
+
should "be able to add_to_set in an embedded hash" do
|
205
|
+
p1 = Person.new(:name => "Jordan")
|
206
|
+
assert p1.insert!
|
207
|
+
p1.add_to_set!("colors.hot", ["red", "pink", "orange"])
|
208
|
+
assert_equal ["red", "pink", "orange"], p1["colors"]["hot"]
|
209
|
+
p1 = Person.find_one(p1["_id"])
|
210
|
+
assert_equal ["red", "pink", "orange"], p1["colors"]["hot"]
|
211
|
+
end
|
212
|
+
|
213
|
+
should "be able to pop_last" do
|
214
|
+
p1 = Person.new(:name => "Jordan")
|
215
|
+
p1["numbers"] = [1,2,3,4,5]
|
216
|
+
assert p1.insert!
|
217
|
+
p1.pop_last!("numbers")
|
218
|
+
assert_equal [1,2,3,4], p1["numbers"]
|
219
|
+
p1 = Person.find_one(p1["_id"])
|
220
|
+
assert_equal [1,2,3,4], p1["numbers"]
|
221
|
+
end
|
222
|
+
|
223
|
+
should "be able to pop_last in an embedded doc" do
|
224
|
+
p1 = Person.new(:name => "Jordan")
|
225
|
+
p1["stats"] = { "numbers" => [1,2,3,4,5] }
|
226
|
+
assert p1.insert!
|
227
|
+
p1.pop_last!("stats.numbers")
|
228
|
+
assert_equal [1,2,3,4], p1["stats"]["numbers"]
|
229
|
+
p1 = Person.find_one(p1["_id"])
|
230
|
+
assert_equal [1,2,3,4], p1["stats"]["numbers"]
|
231
|
+
end
|
232
|
+
|
233
|
+
should "be able to pop_first" do
|
234
|
+
p1 = Person.new(:name => "Jordan")
|
235
|
+
p1["numbers"] = [1,2,3,4,5]
|
236
|
+
assert p1.insert!
|
237
|
+
p1.pop_first!("numbers")
|
238
|
+
assert_equal [2,3,4,5], p1["numbers"]
|
239
|
+
p1 = Person.find_one(p1["_id"])
|
240
|
+
assert_equal [2,3,4,5], p1["numbers"]
|
241
|
+
end
|
242
|
+
|
243
|
+
should "be able to pop_first in an embedded doc" do
|
244
|
+
p1 = Person.new(:name => "Jordan")
|
245
|
+
p1["stats"] = { "numbers" => [1,2,3,4,5] }
|
246
|
+
assert p1.insert!
|
247
|
+
p1.pop_first!("stats.numbers")
|
248
|
+
assert_equal [2,3,4,5], p1["stats"]["numbers"]
|
249
|
+
p1 = Person.find_one(p1["_id"])
|
250
|
+
assert_equal [2,3,4,5], p1["stats"]["numbers"]
|
251
|
+
end
|
252
|
+
|
253
|
+
end
|
data/test/test_mongomatic.rb
CHANGED
@@ -251,6 +251,60 @@ class TestMongomatic < Test::Unit::TestCase
|
|
251
251
|
assert_equal ['Dead must be false'], p.errors.full_messages
|
252
252
|
end
|
253
253
|
|
254
|
+
should "be able to use be_expected with a block" do
|
255
|
+
p = Person.new
|
256
|
+
class << p
|
257
|
+
def validate
|
258
|
+
expectations do
|
259
|
+
be_expected lambda { self['name'].is_a? String }, "Name must be a string"
|
260
|
+
not_be_expected lambda { self['alive'] && self['dead'] }, "Cannot be alive and dead"
|
261
|
+
end
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
p['name'] = 1
|
266
|
+
assert !p.valid?
|
267
|
+
assert_equal p.errors.full_messages, ["Name must be a string"]
|
268
|
+
|
269
|
+
p['alive'] = true
|
270
|
+
p['dead'] = true
|
271
|
+
p['name'] = "Jordan"
|
272
|
+
|
273
|
+
assert !p.valid?
|
274
|
+
assert_equal p.errors.full_messages, ["Cannot be alive and dead"]
|
275
|
+
|
276
|
+
p['dead'] = false
|
277
|
+
assert p.valid?
|
278
|
+
end
|
279
|
+
|
280
|
+
should "be able to use be_expected with a method call" do
|
281
|
+
p = Person.new
|
282
|
+
class << p
|
283
|
+
def validate
|
284
|
+
expectations do
|
285
|
+
be_expected :method_1, "Method 1 must return true"
|
286
|
+
not_be_expected :method_2, "Method 2 must return false"
|
287
|
+
end
|
288
|
+
end
|
289
|
+
|
290
|
+
def method_1
|
291
|
+
(self['name'] == 'Jordan') ? true : false
|
292
|
+
end
|
293
|
+
|
294
|
+
def method_2
|
295
|
+
(self['age'] == 21) ? false : true
|
296
|
+
end
|
297
|
+
end
|
298
|
+
|
299
|
+
assert !p.valid?
|
300
|
+
assert_equal ["Method 1 must return true", "Method 2 must return false"], p.errors.full_messages
|
301
|
+
|
302
|
+
p['name'] = 'Jordan'
|
303
|
+
p['age'] = 21
|
304
|
+
|
305
|
+
assert p.valid?
|
306
|
+
end
|
307
|
+
|
254
308
|
should "be able to use the be_present expectation" do
|
255
309
|
p = Person.new
|
256
310
|
class << p
|
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
|
-
-
|
8
|
-
-
|
9
|
-
version: 0.
|
7
|
+
- 4
|
8
|
+
- 1
|
9
|
+
version: 0.4.1
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Ben Myles
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-08-
|
17
|
+
date: 2010-08-24 00:00:00 -07:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -116,6 +116,7 @@ files:
|
|
116
116
|
- LICENSE
|
117
117
|
- README.rdoc
|
118
118
|
- test/helper.rb
|
119
|
+
- test/test_modifiers.rb
|
119
120
|
- test/test_mongomatic.rb
|
120
121
|
has_rdoc: true
|
121
122
|
homepage: http://mongomatic.com/
|
@@ -151,4 +152,5 @@ specification_version: 3
|
|
151
152
|
summary: Mongomatic is a simple Ruby object mapper for Mongo
|
152
153
|
test_files:
|
153
154
|
- test/helper.rb
|
155
|
+
- test/test_modifiers.rb
|
154
156
|
- test/test_mongomatic.rb
|