mongomatic 0.3.2 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -6,11 +6,25 @@ module Mongomatic
6
6
  end
7
7
 
8
8
  def to_be
9
- add_error_msg unless value
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
- add_error_msg if value
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
@@ -80,7 +80,7 @@ module Mongomatic
80
80
  end
81
81
 
82
82
  def add_error_msg
83
- instance.errors << [message]
83
+ instance.errors << Array(message)
84
84
  end
85
85
  end
86
86
  end
@@ -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, an error condition is raised.
8
- # user.push("interests", "skydiving")
9
- def push(field, val, do_reload=true)
10
- field = field.to_s
11
- if update({}, { "$push" => { field => val } })
12
- reload if do_reload; true
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, do_reload=true)
22
- field = field.to_s
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
- if update({}, { "$pushAll" => { field => val } })
25
- reload if do_reload; true
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, do_reload=true)
34
- field = field.to_s
35
- if update({}, { "$pull" => { field => val } })
36
- reload if do_reload; true
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, do_reload=true)
45
- field = field.to_s
46
- if update({}, { "$pullAll" => { field => val } })
47
- reload if do_reload; true
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, do_reload=true)
55
- field = field.to_s
56
- if update({}, { "$inc" => { field => val } })
57
- reload if do_reload; true
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, do_reload=true)
65
- field = field.to_s
66
- if update({}, { "$set" => { field => val } })
67
- reload if do_reload; true
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, do_reload=true)
75
- field = field.to_s
76
- if update({}, { "$unset" => { field => 1 } })
77
- reload if do_reload; true
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, do_reload=true)
87
- field = field.to_s
88
- if update({}, { "$addToSet" => { field => val } })
89
- reload if do_reload; true
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, do_reload=true)
97
- field = field.to_s
98
- if update({}, { "$pop" => { field => 1 } })
99
- reload if do_reload; true
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, do_reload=true)
107
- field = field.to_s
108
- if update({}, { "$pop" => { field => -1 } })
109
- reload if do_reload; true
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
@@ -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
- - 3
8
- - 2
9
- version: 0.3.2
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-19 00:00:00 -07:00
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