ohm 0.1.0.rc5 → 0.1.0.rc6
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/Rakefile +2 -13
- data/lib/ohm.rb +54 -97
- data/lib/ohm/key.rb +4 -31
- data/lib/ohm/version.rb +1 -1
- data/test/1.8.6_test.rb +18 -18
- data/test/associations_test.rb +100 -0
- data/test/connection_test.rb +33 -21
- data/test/errors_test.rb +88 -88
- data/test/hash_key_test.rb +16 -23
- data/test/helper.rb +25 -0
- data/test/indices_test.rb +177 -183
- data/test/json_test.rb +67 -0
- data/test/model_test.rb +675 -868
- data/test/mutex_test.rb +65 -70
- data/test/pattern_test.rb +8 -6
- data/test/upgrade_script_test.rb +41 -47
- data/test/validations_test.rb +180 -164
- data/test/wrapper_test.rb +7 -5
- metadata +26 -10
- data/test/all_tests.rb +0 -2
- data/test/test_helper.rb +0 -53
data/test/json_test.rb
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require File.expand_path("./helper", File.dirname(__FILE__))
|
4
|
+
|
5
|
+
require "json"
|
6
|
+
|
7
|
+
class Venue < Ohm::Model
|
8
|
+
attribute :name
|
9
|
+
|
10
|
+
def validate
|
11
|
+
assert_present :name
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class Programmer < Ohm::Model
|
16
|
+
attribute :language
|
17
|
+
|
18
|
+
def validate
|
19
|
+
assert_present :language
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_hash
|
23
|
+
super.merge(:language => language)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
test "export an empty hash via to_hash" do
|
28
|
+
person = Venue.new
|
29
|
+
assert Hash.new == person.to_hash
|
30
|
+
end
|
31
|
+
|
32
|
+
test "export a hash with the errors" do
|
33
|
+
person = Venue.new
|
34
|
+
person.valid?
|
35
|
+
|
36
|
+
assert Hash[:errors => [[:name, :not_present]]] == person.to_hash
|
37
|
+
end
|
38
|
+
|
39
|
+
test "export a hash with the its id" do
|
40
|
+
person = Venue.create(:name => "John Doe")
|
41
|
+
assert Hash[:id => '1'] == person.to_hash
|
42
|
+
end
|
43
|
+
|
44
|
+
test "export a hash with its id and the errors" do
|
45
|
+
person = Venue.create(:name => "John Doe")
|
46
|
+
person.name = nil
|
47
|
+
person.valid?
|
48
|
+
|
49
|
+
expected_hash = { :id => '1', :errors => [[:name, :not_present]] }
|
50
|
+
|
51
|
+
assert expected_hash == person.to_hash
|
52
|
+
end
|
53
|
+
|
54
|
+
test "return the merged attributes" do
|
55
|
+
programmer = Programmer.create(:language => "Ruby")
|
56
|
+
expected_hash = { :id => '1', :language => 'Ruby' }
|
57
|
+
|
58
|
+
assert expected_hash == programmer.to_hash
|
59
|
+
end
|
60
|
+
|
61
|
+
test "just be the to_hash of a model" do
|
62
|
+
json = JSON.parse(Programmer.create(:language => "Ruby").to_json)
|
63
|
+
|
64
|
+
assert ["id", "language"] == json.keys.sort
|
65
|
+
assert "1" == json["id"]
|
66
|
+
assert "Ruby" == json["language"]
|
67
|
+
end
|
data/test/model_test.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
# encoding: UTF-8
|
2
2
|
|
3
|
-
require File.expand_path(File.
|
3
|
+
require File.expand_path("./helper", File.dirname(__FILE__))
|
4
|
+
|
4
5
|
require "ostruct"
|
5
|
-
require "json"
|
6
6
|
|
7
7
|
class Post < Ohm::Model
|
8
8
|
attribute :body
|
@@ -46,1099 +46,906 @@ module SomeNamespace
|
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
49
|
-
class
|
50
|
-
|
51
|
-
|
52
|
-
Logger.current.clear
|
53
|
-
end
|
54
|
-
|
55
|
-
context "An event initialized with a hash of attributes" do
|
56
|
-
should "assign the passed attributes" do
|
57
|
-
event = Event.new(:name => "Ruby Tuesday")
|
58
|
-
assert_equal event.name, "Ruby Tuesday"
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
context "An event created from a hash of attributes" do
|
63
|
-
should "assign an id and save the object" do
|
64
|
-
event1 = Event.create(:name => "Ruby Tuesday")
|
65
|
-
event2 = Event.create(:name => "Ruby Meetup")
|
66
|
-
|
67
|
-
assert_equal "1", event1.id
|
68
|
-
assert_equal "2", event2.id
|
69
|
-
end
|
49
|
+
class Meetup < Ohm::Model
|
50
|
+
attribute :name
|
51
|
+
attribute :location
|
70
52
|
|
71
|
-
|
72
|
-
|
73
|
-
end
|
53
|
+
def validate
|
54
|
+
assert_present :name
|
74
55
|
end
|
56
|
+
end
|
75
57
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
def validate
|
82
|
-
assert_present :name
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
should "assign an id and save the object" do
|
87
|
-
event = Meetup.create(:name => "Ruby Tuesday")
|
88
|
-
event.update(:name => "Ruby Meetup")
|
89
|
-
assert_equal "Ruby Meetup", event.name
|
90
|
-
end
|
91
|
-
|
92
|
-
should "return false if the validation fails" do
|
93
|
-
event = Meetup.create(:name => "Ruby Tuesday")
|
94
|
-
assert !event.update(:name => nil)
|
95
|
-
end
|
96
|
-
|
97
|
-
should "save the attributes in UTF8" do
|
98
|
-
event = Meetup.create(:name => "32° Kisei-sen")
|
99
|
-
assert_equal "32° Kisei-sen", Meetup[event.id].name
|
100
|
-
end
|
101
|
-
|
102
|
-
should "delete the attribute if set to nil" do
|
103
|
-
event = Meetup.create(:name => "Ruby Tuesday", :location => "Los Angeles")
|
104
|
-
assert_equal "Los Angeles", Meetup[event.id].location
|
105
|
-
assert event.update(:location => nil)
|
106
|
-
assert_equal nil, Meetup[event.id].location
|
107
|
-
end
|
108
|
-
|
109
|
-
should "delete the attribute if set to an empty string" do
|
110
|
-
event = Meetup.create(:name => "Ruby Tuesday", :location => "Los Angeles")
|
111
|
-
assert_equal "Los Angeles", Meetup[event.id].location
|
112
|
-
assert event.update(:location => "")
|
113
|
-
assert_equal nil, Meetup[event.id].location
|
114
|
-
end
|
115
|
-
end
|
58
|
+
test "assign attributes from the hash" do
|
59
|
+
event = Event.new(:name => "Ruby Tuesday")
|
60
|
+
assert event.name == "Ruby Tuesday"
|
61
|
+
end
|
116
62
|
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
class RedefinedModel < Ohm::Model
|
121
|
-
attribute :name
|
122
|
-
|
123
|
-
silence_warnings do
|
124
|
-
attribute :name
|
125
|
-
end
|
126
|
-
end
|
127
|
-
end
|
128
|
-
end
|
63
|
+
test "assign an ID and save the object" do
|
64
|
+
event1 = Event.create(:name => "Ruby Tuesday")
|
65
|
+
event2 = Event.create(:name => "Ruby Meetup")
|
129
66
|
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
counter :age
|
67
|
+
assert "1" == event1.id
|
68
|
+
assert "2" == event2.id
|
69
|
+
end
|
134
70
|
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
end
|
139
|
-
end
|
140
|
-
end
|
71
|
+
test "return the unsaved object if validation fails" do
|
72
|
+
assert Person.create(:name => nil).kind_of?(Person)
|
73
|
+
end
|
141
74
|
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
75
|
+
test "updates attributes" do
|
76
|
+
event = Meetup.create(:name => "Ruby Tuesday")
|
77
|
+
event.update(:name => "Ruby Meetup")
|
78
|
+
assert "Ruby Meetup" == event.name
|
79
|
+
end
|
146
80
|
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
end
|
152
|
-
end
|
81
|
+
test "return false if the validation fails" do
|
82
|
+
event = Meetup.create(:name => "Ruby Tuesday")
|
83
|
+
assert !event.update(:name => nil)
|
84
|
+
end
|
153
85
|
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
86
|
+
test "save the attributes in UTF8" do
|
87
|
+
event = Meetup.create(:name => "32° Kisei-sen")
|
88
|
+
assert "32° Kisei-sen" == Meetup[event.id].name
|
89
|
+
end
|
158
90
|
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
91
|
+
test "delete the attribute if set to nil" do
|
92
|
+
event = Meetup.create(:name => "Ruby Tuesday", :location => "Los Angeles")
|
93
|
+
assert "Los Angeles" == Meetup[event.id].location
|
94
|
+
assert event.update(:location => nil)
|
95
|
+
assert nil == Meetup[event.id].location
|
96
|
+
end
|
165
97
|
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
98
|
+
test "delete the attribute if set to an empty string" do
|
99
|
+
event = Meetup.create(:name => "Ruby Tuesday", :location => "Los Angeles")
|
100
|
+
assert "Los Angeles" == Meetup[event.id].location
|
101
|
+
assert event.update(:location => "")
|
102
|
+
assert nil == Meetup[event.id].location
|
103
|
+
end
|
170
104
|
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
end
|
175
|
-
end
|
176
|
-
end
|
105
|
+
test "not raise if an attribute is redefined" do
|
106
|
+
class RedefinedModel < Ohm::Model
|
107
|
+
attribute :name
|
177
108
|
|
178
|
-
|
179
|
-
|
180
|
-
class RedefinedModel < Ohm::Model
|
181
|
-
attribute :color
|
182
|
-
index :color
|
183
|
-
index :color
|
184
|
-
end
|
185
|
-
end
|
109
|
+
silence_warnings do
|
110
|
+
attribute :name
|
186
111
|
end
|
187
112
|
end
|
113
|
+
end
|
188
114
|
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
Ohm.redis.hset("Event:1", "name", "Concert")
|
193
|
-
end
|
115
|
+
test "not raise if a counter is redefined" do
|
116
|
+
class RedefinedModel < Ohm::Model
|
117
|
+
counter :age
|
194
118
|
|
195
|
-
|
196
|
-
|
197
|
-
assert_equal 1, Event[1].id
|
198
|
-
assert_equal "Concert", Event[1].name
|
119
|
+
silence_warnings do
|
120
|
+
counter :age
|
199
121
|
end
|
200
122
|
end
|
123
|
+
end
|
201
124
|
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
Ohm.redis.hset("User:1", "email", "albert@example.com")
|
206
|
-
end
|
207
|
-
|
208
|
-
should "return an instance of User" do
|
209
|
-
assert User[1].kind_of?(User)
|
210
|
-
assert_equal 1, User[1].id
|
211
|
-
assert_equal "albert@example.com", User[1].email
|
212
|
-
end
|
125
|
+
test "not raise if a list is redefined" do
|
126
|
+
class RedefinedModel < Ohm::Model
|
127
|
+
list :todo, lambda { }
|
213
128
|
|
214
|
-
|
215
|
-
|
129
|
+
silence_warnings do
|
130
|
+
list :todo, lambda { }
|
216
131
|
end
|
217
132
|
end
|
133
|
+
end
|
218
134
|
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
Ohm.redis.set("User:1:email", "albert@example.com")
|
223
|
-
|
224
|
-
@user = User[1]
|
225
|
-
end
|
135
|
+
test "not raise if a set is redefined" do
|
136
|
+
class RedefinedModel < Ohm::Model
|
137
|
+
set :friends, lambda { }
|
226
138
|
|
227
|
-
|
228
|
-
|
229
|
-
assert_equal "maria@example.com", @user.email
|
139
|
+
silence_warnings do
|
140
|
+
set :friends, lambda { }
|
230
141
|
end
|
142
|
+
end
|
143
|
+
end
|
231
144
|
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
@user.email = "maria@example.com"
|
237
|
-
@user.save
|
145
|
+
test "not raise if a collection is redefined" do
|
146
|
+
class RedefinedModel < Ohm::Model
|
147
|
+
list :toys, lambda { }
|
238
148
|
|
239
|
-
|
149
|
+
silence_warnings do
|
150
|
+
set :toys, lambda { }
|
240
151
|
end
|
241
152
|
end
|
153
|
+
end
|
242
154
|
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
event2 = Event.new
|
249
|
-
event2.create
|
250
|
-
|
251
|
-
assert !event1.new?
|
252
|
-
assert !event2.new?
|
253
|
-
|
254
|
-
assert_equal "1", event1.id
|
255
|
-
assert_equal "2", event2.id
|
256
|
-
end
|
155
|
+
test "not raise if a index is redefined" do
|
156
|
+
class RedefinedModel < Ohm::Model
|
157
|
+
attribute :color
|
158
|
+
index :color
|
159
|
+
index :color
|
257
160
|
end
|
161
|
+
end
|
258
162
|
|
259
|
-
|
260
|
-
|
261
|
-
event = Event.new(:name => "Foo").save
|
262
|
-
assert_equal "Foo", Event[event.id].name
|
263
|
-
end
|
163
|
+
test "allow arbitrary IDs" do
|
164
|
+
Event.create(:id => "abc123", :name => "Concert")
|
264
165
|
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
event.create
|
166
|
+
assert Event.all.size == 1
|
167
|
+
assert Event["abc123"].name == "Concert"
|
168
|
+
end
|
269
169
|
|
270
|
-
|
271
|
-
|
170
|
+
setup do
|
171
|
+
Ohm.redis.sadd("Event:all", 1)
|
172
|
+
Ohm.redis.hset("Event:1", "name", "Concert")
|
173
|
+
end
|
272
174
|
|
273
|
-
|
274
|
-
|
175
|
+
test "return an instance of Event" do
|
176
|
+
assert Event[1].kind_of?(Event)
|
177
|
+
assert 1 == Event[1].id
|
178
|
+
assert "Concert" == Event[1].name
|
179
|
+
end
|
275
180
|
|
276
|
-
|
277
|
-
|
181
|
+
setup do
|
182
|
+
Ohm.redis.sadd("User:all", 1)
|
183
|
+
Ohm.redis.hset("User:1", "email", "albert@example.com")
|
184
|
+
end
|
278
185
|
|
279
|
-
|
280
|
-
|
186
|
+
test "return an instance of User" do
|
187
|
+
assert User[1].kind_of?(User)
|
188
|
+
assert 1 == User[1].id
|
189
|
+
assert "albert@example.com" == User[1].email
|
190
|
+
end
|
281
191
|
|
282
|
-
|
283
|
-
|
192
|
+
test "allow to map key to models" do
|
193
|
+
assert [User[1]] == [1].map(&User)
|
194
|
+
end
|
284
195
|
|
285
|
-
|
286
|
-
|
196
|
+
setup do
|
197
|
+
Ohm.redis.sadd("User:all", 1)
|
198
|
+
Ohm.redis.set("User:1:email", "albert@example.com")
|
287
199
|
|
288
|
-
|
289
|
-
|
200
|
+
@user = User[1]
|
201
|
+
end
|
290
202
|
|
291
|
-
|
203
|
+
test "change its attributes" do
|
204
|
+
@user.email = "maria@example.com"
|
205
|
+
assert "maria@example.com" == @user.email
|
206
|
+
end
|
292
207
|
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
attribute :name
|
297
|
-
set :foos, Post
|
298
|
-
list :bars, Post
|
299
|
-
end
|
208
|
+
test "save the new values" do
|
209
|
+
@user.email = "maria@example.com"
|
210
|
+
@user.save
|
300
211
|
|
301
|
-
|
212
|
+
@user.email = "maria@example.com"
|
213
|
+
@user.save
|
302
214
|
|
303
|
-
|
304
|
-
|
215
|
+
assert "maria@example.com" == User[1].email
|
216
|
+
end
|
305
217
|
|
306
|
-
|
218
|
+
test "assign a new id to the event" do
|
219
|
+
event1 = Event.new
|
220
|
+
event1.create
|
307
221
|
|
308
|
-
|
222
|
+
event2 = Event.new
|
223
|
+
event2.create
|
309
224
|
|
310
|
-
|
311
|
-
|
312
|
-
assert_equal Array.new, Ohm.redis.smembers(ModelToBeDeleted.key[id][:foos])
|
313
|
-
assert_equal Array.new, Ohm.redis.lrange(ModelToBeDeleted.key[id][:bars], 0, -1)
|
225
|
+
assert !event1.new?
|
226
|
+
assert !event2.new?
|
314
227
|
|
315
|
-
|
316
|
-
|
228
|
+
assert "1" == event1.id
|
229
|
+
assert "2" == event2.id
|
230
|
+
end
|
317
231
|
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
232
|
+
# Saving a model
|
233
|
+
test "create the model if it is new" do
|
234
|
+
event = Event.new(:name => "Foo").save
|
235
|
+
assert "Foo" == Event[event.id].name
|
236
|
+
end
|
323
237
|
|
324
|
-
|
238
|
+
test "save it only if it was previously created" do
|
239
|
+
event = Event.new
|
240
|
+
event.name = "Lorem ipsum"
|
241
|
+
event.create
|
325
242
|
|
326
|
-
|
243
|
+
event.name = "Lorem"
|
244
|
+
event.save
|
327
245
|
|
328
|
-
|
246
|
+
assert "Lorem" == Event[event.id].name
|
247
|
+
end
|
329
248
|
|
330
|
-
|
249
|
+
test "allow to hook into write" do
|
250
|
+
event = Event.create(:name => "Foo")
|
331
251
|
|
332
|
-
|
333
|
-
|
334
|
-
end
|
252
|
+
assert "foo" == event.slug
|
253
|
+
end
|
335
254
|
|
336
|
-
|
337
|
-
|
338
|
-
event1 = Event.new
|
339
|
-
event1.name = "Ruby Meetup"
|
340
|
-
event1.create
|
255
|
+
test "save counters" do
|
256
|
+
event = Event.create(:name => "Foo")
|
341
257
|
|
342
|
-
|
343
|
-
|
344
|
-
event2.create
|
258
|
+
event.incr(:votes)
|
259
|
+
event.save
|
345
260
|
|
346
|
-
|
261
|
+
assert 1 == Event[event.id].votes
|
262
|
+
end
|
347
263
|
|
348
|
-
|
349
|
-
|
350
|
-
|
264
|
+
# Delete
|
265
|
+
test "delete an existing model" do
|
266
|
+
class ModelToBeDeleted < Ohm::Model
|
267
|
+
attribute :name
|
268
|
+
set :foos, Post
|
269
|
+
list :bars, Post
|
351
270
|
end
|
352
271
|
|
353
|
-
|
354
|
-
should "sort all" do
|
355
|
-
Person.create :name => "D"
|
356
|
-
Person.create :name => "C"
|
357
|
-
Person.create :name => "B"
|
358
|
-
Person.create :name => "A"
|
359
|
-
|
360
|
-
assert_equal %w[A B C D], Person.all.sort_by(:name, :order => "ALPHA").map { |person| person.name }
|
361
|
-
end
|
362
|
-
|
363
|
-
should "return an empty array if there are no elements to sort" do
|
364
|
-
assert_equal [], Person.all.sort_by(:name)
|
365
|
-
end
|
366
|
-
|
367
|
-
should "return the first element sorted by id when using first" do
|
368
|
-
Person.create :name => "A"
|
369
|
-
Person.create :name => "B"
|
370
|
-
assert_equal "A", Person.all.first.name
|
371
|
-
end
|
372
|
-
|
373
|
-
should "return the first element sorted by name if first receives a sorting option" do
|
374
|
-
Person.create :name => "B"
|
375
|
-
Person.create :name => "A"
|
376
|
-
assert_equal "A", Person.all.first(:by => :name, :order => "ALPHA").name
|
377
|
-
end
|
378
|
-
|
379
|
-
should "return attribute values when the get parameter is specified" do
|
380
|
-
Person.create :name => "B"
|
381
|
-
Person.create :name => "A"
|
382
|
-
|
383
|
-
assert_equal "A", Person.all.sort_by(:name, :get => :name, :order => "ALPHA").first
|
384
|
-
end
|
385
|
-
end
|
272
|
+
@model = ModelToBeDeleted.create(:name => "Lorem")
|
386
273
|
|
387
|
-
|
388
|
-
|
389
|
-
event = Event.new
|
390
|
-
event.name = "Ruby Tuesday"
|
391
|
-
@id = event.create.id
|
392
|
-
end
|
274
|
+
@model.foos << Post.create
|
275
|
+
@model.bars << Post.create
|
393
276
|
|
394
|
-
|
395
|
-
event = Event[@id]
|
277
|
+
id = @model.id
|
396
278
|
|
397
|
-
|
279
|
+
@model.delete
|
398
280
|
|
399
|
-
|
400
|
-
|
401
|
-
|
281
|
+
assert Ohm.redis.get(ModelToBeDeleted.key[id]).nil?
|
282
|
+
assert Ohm.redis.get(ModelToBeDeleted.key[id][:name]).nil?
|
283
|
+
assert Array.new == Ohm.redis.smembers(ModelToBeDeleted.key[id][:foos])
|
284
|
+
assert Array.new == Ohm.redis.lrange(ModelToBeDeleted.key[id][:bars], 0, -1)
|
402
285
|
|
403
|
-
|
404
|
-
|
405
|
-
assert Logger.current.commands.empty?
|
406
|
-
end
|
286
|
+
assert ModelToBeDeleted.all.empty?
|
287
|
+
end
|
407
288
|
|
408
|
-
|
409
|
-
|
289
|
+
setup do
|
290
|
+
end
|
410
291
|
|
411
|
-
|
412
|
-
|
292
|
+
test "be no leftover keys" do
|
293
|
+
class ::Foo < Ohm::Model
|
294
|
+
attribute :name
|
295
|
+
index :name
|
413
296
|
end
|
414
297
|
|
415
|
-
|
416
|
-
setup do
|
417
|
-
@person1 = Person.create(:name => "Albert")
|
418
|
-
@person2 = Person.create(:name => "Bertrand")
|
419
|
-
@person3 = Person.create(:name => "Charles")
|
298
|
+
assert [] == Ohm.redis.keys("*")
|
420
299
|
|
421
|
-
|
422
|
-
@event.name = "Ruby Tuesday"
|
423
|
-
end
|
300
|
+
Foo.create(:name => "Bar")
|
424
301
|
|
425
|
-
|
426
|
-
assert_raise Ohm::Model::MissingID do
|
427
|
-
@event.attendees << Person.new
|
428
|
-
end
|
429
|
-
end
|
302
|
+
assert ["Foo:1:_indices", "Foo:1", "Foo:all", "Foo:id", "Foo:name:QmFy"].sort == Ohm.redis.keys("*").sort
|
430
303
|
|
431
|
-
|
432
|
-
@event.create
|
433
|
-
@event.attendees << @person1
|
434
|
-
@event.attendees << @person2
|
435
|
-
@event.attendees << @person3
|
436
|
-
assert_equal ["1", "2", "3"], @event.attendees.key.sort
|
437
|
-
@event.attendees.delete(@person2)
|
438
|
-
assert_equal ["1", "3"], Event[@event.id].attendees.key.sort
|
439
|
-
end
|
440
|
-
|
441
|
-
should "return true if the set includes some member" do
|
442
|
-
@event.create
|
443
|
-
@event.attendees << @person1
|
444
|
-
@event.attendees << @person2
|
445
|
-
assert @event.attendees.include?(@person2)
|
446
|
-
assert !@event.attendees.include?(@person3)
|
447
|
-
end
|
304
|
+
Foo[1].delete
|
448
305
|
|
449
|
-
|
450
|
-
|
451
|
-
@event.attendees << @person1
|
452
|
-
|
453
|
-
assert_equal [@person1], @event.attendees.all
|
454
|
-
assert_equal @person1, @event.attendees[@person1.id]
|
455
|
-
end
|
306
|
+
assert ["Foo:id"] == Ohm.redis.keys("*")
|
307
|
+
end
|
456
308
|
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
assert_equal 3, @event.attendees.size
|
463
|
-
end
|
309
|
+
# Listing
|
310
|
+
test "find all" do
|
311
|
+
event1 = Event.new
|
312
|
+
event1.name = "Ruby Meetup"
|
313
|
+
event1.create
|
464
314
|
|
465
|
-
|
466
|
-
|
467
|
-
|
315
|
+
event2 = Event.new
|
316
|
+
event2.name = "Ruby Tuesday"
|
317
|
+
event2.create
|
468
318
|
|
469
|
-
|
319
|
+
all = Event.all
|
470
320
|
|
471
|
-
|
472
|
-
|
321
|
+
assert all.detect {|e| e.name == "Ruby Meetup" }
|
322
|
+
assert all.detect {|e| e.name == "Ruby Tuesday" }
|
323
|
+
end
|
473
324
|
|
474
|
-
|
475
|
-
|
476
|
-
|
325
|
+
# Sorting
|
326
|
+
test "sort all" do
|
327
|
+
Person.create :name => "D"
|
328
|
+
Person.create :name => "C"
|
329
|
+
Person.create :name => "B"
|
330
|
+
Person.create :name => "A"
|
477
331
|
|
478
|
-
|
332
|
+
assert %w[A B C D] == Person.all.sort_by(:name, :order => "ALPHA").map { |person| person.name }
|
333
|
+
end
|
479
334
|
|
480
|
-
|
335
|
+
test "return an empty array if there are no elements to sort" do
|
336
|
+
assert [] == Person.all.sort_by(:name)
|
337
|
+
end
|
481
338
|
|
482
|
-
|
483
|
-
|
339
|
+
test "return the first element sorted by id when using first" do
|
340
|
+
Person.create :name => "A"
|
341
|
+
Person.create :name => "B"
|
342
|
+
assert "A" == Person.all.first.name
|
343
|
+
end
|
484
344
|
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
345
|
+
test "return the first element sorted by name if first receives a sorting option" do
|
346
|
+
Person.create :name => "B"
|
347
|
+
Person.create :name => "A"
|
348
|
+
assert "A" == Person.all.first(:by => :name, :order => "ALPHA").name
|
349
|
+
end
|
489
350
|
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
end
|
494
|
-
end
|
351
|
+
test "return attribute values when the get parameter is specified" do
|
352
|
+
Person.create :name => "B"
|
353
|
+
Person.create :name => "A"
|
495
354
|
|
496
|
-
|
497
|
-
|
498
|
-
@post = Post.new
|
499
|
-
@post.body = "Hello world!"
|
500
|
-
@post.create
|
501
|
-
end
|
355
|
+
assert "A" == Person.all.sort_by(:name, :get => :name, :order => "ALPHA").first
|
356
|
+
end
|
502
357
|
|
503
|
-
|
504
|
-
|
505
|
-
|
358
|
+
test "work on lists" do
|
359
|
+
@post = Post.create :body => "Hello world!"
|
360
|
+
@post.related << Post.create(:body => "C")
|
361
|
+
@post.related << Post.create(:body => "B")
|
362
|
+
@post.related << Post.create(:body => "A")
|
506
363
|
|
507
|
-
|
508
|
-
|
509
|
-
@post.related << Post.create
|
364
|
+
assert ["A", "B", "C"] == @post.related.sort_by(:body, :order => "ALPHA ASC").map { |model| model.body }
|
365
|
+
end
|
510
366
|
|
511
|
-
|
512
|
-
|
367
|
+
# Loading attributes
|
368
|
+
setup do
|
369
|
+
event = Event.new
|
370
|
+
event.name = "Ruby Tuesday"
|
371
|
+
@id = event.create.id
|
372
|
+
end
|
513
373
|
|
514
|
-
|
515
|
-
|
516
|
-
@post.related << Post.create
|
517
|
-
@post.related << Post.create
|
518
|
-
assert_equal ["2", "3", "4"], @post.related.all.map { |model| model.id }
|
519
|
-
end
|
374
|
+
def monitor
|
375
|
+
log = []
|
520
376
|
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
@post.save
|
526
|
-
assert_equal ["2", "3", "4"], Post[@post.id].related.map { |model| model.id }
|
377
|
+
monitor = Thread.new do
|
378
|
+
Redis.connect.monitor do |line|
|
379
|
+
break if line =~ /ping/
|
380
|
+
log << line
|
527
381
|
end
|
382
|
+
end
|
528
383
|
|
529
|
-
|
530
|
-
post1 = Post.create
|
531
|
-
post2 = Post.create
|
532
|
-
post3 = Post.create
|
533
|
-
|
534
|
-
@post.related << post1
|
535
|
-
@post.related << post2
|
536
|
-
@post.related << post3
|
384
|
+
sleep 0.01
|
537
385
|
|
538
|
-
|
539
|
-
|
540
|
-
|
386
|
+
log.clear.tap do
|
387
|
+
yield
|
388
|
+
Ohm.redis.ping
|
389
|
+
monitor.join
|
390
|
+
end
|
391
|
+
end
|
541
392
|
|
542
|
-
|
393
|
+
test "load attributes lazily" do
|
394
|
+
event = Event[@id]
|
543
395
|
|
544
|
-
|
545
|
-
assert_equal [post2, post3], @post.related[1, -1]
|
396
|
+
log = monitor { event.name }
|
546
397
|
|
547
|
-
|
398
|
+
assert !log.empty?
|
548
399
|
|
549
|
-
|
550
|
-
assert_equal [post2, post3], @post.related[1..5]
|
400
|
+
log = monitor { event.name }
|
551
401
|
|
552
|
-
|
553
|
-
|
402
|
+
assert log.empty?
|
403
|
+
end
|
554
404
|
|
555
|
-
|
556
|
-
|
557
|
-
@post.related << Post.create
|
558
|
-
@post.related << Post.create
|
405
|
+
test "load attributes as a strings" do
|
406
|
+
event = Event.create(:name => 1)
|
559
407
|
|
560
|
-
|
561
|
-
|
562
|
-
assert_equal i, c.id.to_i
|
563
|
-
i += 1
|
564
|
-
end
|
565
|
-
end
|
408
|
+
assert "1" == Event[event.id].name
|
409
|
+
end
|
566
410
|
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
end
|
411
|
+
# Attributes of type Set
|
412
|
+
setup do
|
413
|
+
@person1 = Person.create(:name => "Albert")
|
414
|
+
@person2 = Person.create(:name => "Bertrand")
|
415
|
+
@person3 = Person.create(:name => "Charles")
|
573
416
|
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
assert_equal "3", @post.related.pop.id
|
578
|
-
assert_equal "2", @post.related.pop.id
|
579
|
-
assert @post.related.empty?
|
580
|
-
end
|
417
|
+
@event = Event.new
|
418
|
+
@event.name = "Ruby Tuesday"
|
419
|
+
end
|
581
420
|
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
assert @post.related.empty?
|
588
|
-
end
|
421
|
+
test "not be available if the model is new" do
|
422
|
+
assert_raise Ohm::Model::MissingID do
|
423
|
+
@event.attendees << Person.new
|
424
|
+
end
|
425
|
+
end
|
589
426
|
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
|
427
|
+
test "remove an element if sent delete" do
|
428
|
+
@event.create
|
429
|
+
@event.attendees << @person1
|
430
|
+
@event.attendees << @person2
|
431
|
+
@event.attendees << @person3
|
432
|
+
assert ["1", "2", "3"] == @event.attendees.key.sort
|
433
|
+
@event.attendees.delete(@person2)
|
434
|
+
assert ["1", "3"] == Event[@event.id].attendees.key.sort
|
435
|
+
end
|
597
436
|
|
598
|
-
|
599
|
-
|
600
|
-
|
437
|
+
test "return true if the set includes some member" do
|
438
|
+
@event.create
|
439
|
+
@event.attendees << @person1
|
440
|
+
@event.attendees << @person2
|
441
|
+
assert @event.attendees.include?(@person2)
|
442
|
+
assert !@event.attendees.include?(@person3)
|
443
|
+
end
|
601
444
|
|
602
|
-
|
603
|
-
|
445
|
+
test "return instances of the passed model" do
|
446
|
+
@event.create
|
447
|
+
@event.attendees << @person1
|
604
448
|
|
605
|
-
|
606
|
-
|
449
|
+
assert [@person1] == @event.attendees.all
|
450
|
+
assert @person1 == @event.attendees[@person1.id]
|
451
|
+
end
|
607
452
|
|
608
|
-
|
609
|
-
|
453
|
+
test "return the size of the set" do
|
454
|
+
@event.create
|
455
|
+
@event.attendees << @person1
|
456
|
+
@event.attendees << @person2
|
457
|
+
@event.attendees << @person3
|
458
|
+
assert 3 == @event.attendees.size
|
459
|
+
end
|
610
460
|
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
end
|
461
|
+
test "empty the set" do
|
462
|
+
@event.create
|
463
|
+
@event.attendees << @person1
|
615
464
|
|
616
|
-
|
617
|
-
another_post = Post.create
|
465
|
+
@event.attendees.clear
|
618
466
|
|
619
|
-
|
467
|
+
assert @event.attendees.empty?
|
468
|
+
end
|
620
469
|
|
621
|
-
|
622
|
-
|
623
|
-
|
470
|
+
test "replace the values in the set" do
|
471
|
+
@event.create
|
472
|
+
@event.attendees << @person1
|
624
473
|
|
625
|
-
|
626
|
-
@post.related.unshift(Post.create(:body => "Hello"))
|
627
|
-
@post.related.unshift(Post.create(:body => "Goodbye"))
|
474
|
+
assert [@person1] == @event.attendees.all
|
628
475
|
|
629
|
-
|
476
|
+
@event.attendees.replace([@person2, @person3])
|
630
477
|
|
631
|
-
|
478
|
+
assert [@person2, @person3] == @event.attendees.all.sort_by(&:id)
|
479
|
+
end
|
632
480
|
|
633
|
-
|
481
|
+
test "filter elements" do
|
482
|
+
@event.create
|
483
|
+
@event.attendees.add(@person1)
|
484
|
+
@event.attendees.add(@person2)
|
634
485
|
|
635
|
-
|
636
|
-
|
637
|
-
|
486
|
+
assert [@person1] == @event.attendees.find(:initial => "A").all
|
487
|
+
assert [@person2] == @event.attendees.find(:initial => "B").all
|
488
|
+
assert [] == @event.attendees.find(:initial => "Z").all
|
489
|
+
end
|
638
490
|
|
639
|
-
|
640
|
-
|
491
|
+
# Attributes of type List
|
492
|
+
setup do
|
493
|
+
@post = Post.new
|
494
|
+
@post.body = "Hello world!"
|
495
|
+
@post.create
|
496
|
+
end
|
641
497
|
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
end
|
498
|
+
test "return an array" do
|
499
|
+
assert @post.related.all.kind_of?(Array)
|
500
|
+
end
|
646
501
|
|
647
|
-
|
648
|
-
|
649
|
-
|
502
|
+
test "append elements with push" do
|
503
|
+
@post.related.push Post.create
|
504
|
+
@post.related << Post.create
|
650
505
|
|
651
|
-
|
652
|
-
|
653
|
-
end
|
654
|
-
end
|
506
|
+
assert ["2", "3"] == @post.related.all.map { |model| model.id }
|
507
|
+
end
|
655
508
|
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
509
|
+
test "keep the inserting order" do
|
510
|
+
@post.related << Post.create
|
511
|
+
@post.related << Post.create
|
512
|
+
@post.related << Post.create
|
513
|
+
assert ["2", "3", "4"] == @post.related.all.map { |model| model.id }
|
514
|
+
end
|
661
515
|
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
|
516
|
+
test "keep the inserting order after saving" do
|
517
|
+
@post.related << Post.create
|
518
|
+
@post.related << Post.create
|
519
|
+
@post.related << Post.create
|
520
|
+
@post.save
|
521
|
+
assert ["2", "3", "4"] == Post[@post.id].related.map { |model| model.id }
|
522
|
+
end
|
666
523
|
|
667
|
-
|
668
|
-
|
524
|
+
test "allow slicing the list" do
|
525
|
+
post1 = Post.create
|
526
|
+
post2 = Post.create
|
527
|
+
post3 = Post.create
|
669
528
|
|
670
|
-
|
671
|
-
|
529
|
+
@post.related << post1
|
530
|
+
@post.related << post2
|
531
|
+
@post.related << post3
|
672
532
|
|
673
|
-
|
674
|
-
|
533
|
+
assert post1 == @post.related[0]
|
534
|
+
assert post2 == @post.related[1]
|
535
|
+
assert post3 == @post.related[-1]
|
675
536
|
|
676
|
-
|
677
|
-
assert_equal [Date.new(2009, 5, 25), Date.new(2009, 7, 9)], @calendar.holidays.all
|
537
|
+
assert nil == @post.related[3]
|
678
538
|
|
679
|
-
|
680
|
-
|
681
|
-
end
|
539
|
+
assert [post2, post3] == @post.related[1, 2]
|
540
|
+
assert [post2, post3] == @post.related[1, -1]
|
682
541
|
|
683
|
-
|
684
|
-
appointment = Appointment.create(:subscriber => MyActiveRecordModel.find(1))
|
685
|
-
assert_equal MyActiveRecordModel.find(1), appointment.subscriber
|
686
|
-
end
|
542
|
+
assert [] == @post.related[4, 5]
|
687
543
|
|
688
|
-
|
689
|
-
|
544
|
+
assert [post2, post3] == @post.related[1..2]
|
545
|
+
assert [post2, post3] == @post.related[1..5]
|
690
546
|
|
691
|
-
|
692
|
-
|
693
|
-
end
|
547
|
+
assert [] == @post.related[4..5]
|
548
|
+
end
|
694
549
|
|
695
|
-
|
696
|
-
|
697
|
-
|
698
|
-
|
699
|
-
@post.related << Post.create
|
700
|
-
@post.related << Post.create
|
701
|
-
end
|
550
|
+
test "respond to each" do
|
551
|
+
@post.related << Post.create
|
552
|
+
@post.related << Post.create
|
553
|
+
@post.related << Post.create
|
702
554
|
|
703
|
-
|
704
|
-
|
705
|
-
|
555
|
+
i = 2
|
556
|
+
@post.related.each do |c|
|
557
|
+
assert i == c.id.to_i
|
558
|
+
i += 1
|
706
559
|
end
|
560
|
+
end
|
707
561
|
|
708
|
-
|
709
|
-
|
710
|
-
|
711
|
-
|
712
|
-
|
713
|
-
|
714
|
-
@event.attendees << Person.create(:name => "A")
|
715
|
-
end
|
562
|
+
test "return the size of the list" do
|
563
|
+
@post.related << Post.create
|
564
|
+
@post.related << Post.create
|
565
|
+
@post.related << Post.create
|
566
|
+
assert 3 == @post.related.size
|
567
|
+
end
|
716
568
|
|
717
|
-
|
718
|
-
|
719
|
-
|
720
|
-
|
569
|
+
test "return the last element with pop" do
|
570
|
+
@post.related << Post.create
|
571
|
+
@post.related << Post.create
|
572
|
+
assert "3" == @post.related.pop.id
|
573
|
+
assert "2" == @post.related.pop.id
|
574
|
+
assert @post.related.empty?
|
575
|
+
end
|
721
576
|
|
722
|
-
|
723
|
-
|
724
|
-
|
725
|
-
|
577
|
+
test "return the first element with shift" do
|
578
|
+
@post.related << Post.create
|
579
|
+
@post.related << Post.create
|
580
|
+
assert "2" == @post.related.shift.id
|
581
|
+
assert "3" == @post.related.shift.id
|
582
|
+
assert @post.related.empty?
|
583
|
+
end
|
726
584
|
|
727
|
-
|
728
|
-
|
729
|
-
|
730
|
-
|
731
|
-
|
585
|
+
test "push to the head of the list with unshift" do
|
586
|
+
@post.related.unshift Post.create
|
587
|
+
@post.related.unshift Post.create
|
588
|
+
assert "2" == @post.related.pop.id
|
589
|
+
assert "3" == @post.related.pop.id
|
590
|
+
assert @post.related.empty?
|
591
|
+
end
|
732
592
|
|
733
|
-
|
734
|
-
|
735
|
-
|
736
|
-
@user.posts.add Post.create(:body => "D")
|
737
|
-
@user.posts.add Post.create(:body => "C")
|
738
|
-
@user.posts.add Post.create(:body => "B")
|
739
|
-
@user.posts.add Post.create(:body => "A")
|
740
|
-
end
|
593
|
+
test "empty the list" do
|
594
|
+
@post.related.unshift Post.create
|
595
|
+
@post.related.clear
|
741
596
|
|
742
|
-
|
743
|
-
|
744
|
-
end
|
745
|
-
end
|
597
|
+
assert @post.related.empty?
|
598
|
+
end
|
746
599
|
|
747
|
-
|
748
|
-
|
749
|
-
@event = Event.create(:name => "Ruby Tuesday")
|
750
|
-
end
|
600
|
+
test "replace the values in the list" do
|
601
|
+
@post.related.replace([Post.create, Post.create])
|
751
602
|
|
752
|
-
|
753
|
-
|
754
|
-
@event.incr(:name)
|
755
|
-
end
|
756
|
-
end
|
603
|
+
assert ["2", "3"] == @post.related.map { |model| model.id }
|
604
|
+
end
|
757
605
|
|
758
|
-
|
759
|
-
|
760
|
-
|
606
|
+
test "add models" do
|
607
|
+
@post.related.add(Post.create(:body => "Hello"))
|
608
|
+
assert ["2"] == @post.related.map { |model| model.id }
|
609
|
+
end
|
761
610
|
|
762
|
-
|
763
|
-
|
764
|
-
assert_equal 1, @event.votes
|
611
|
+
test "find elements in the list" do
|
612
|
+
another_post = Post.create
|
765
613
|
|
766
|
-
|
767
|
-
assert_equal 3, @event.votes
|
768
|
-
end
|
614
|
+
@post.related.add(another_post)
|
769
615
|
|
770
|
-
|
771
|
-
|
772
|
-
|
616
|
+
assert @post.related.include?(another_post)
|
617
|
+
assert !@post.related.include?(Post.create)
|
618
|
+
end
|
773
619
|
|
774
|
-
|
775
|
-
|
776
|
-
|
777
|
-
end
|
620
|
+
test "unshift models" do
|
621
|
+
@post.related.unshift(Post.create(:body => "Hello"))
|
622
|
+
@post.related.unshift(Post.create(:body => "Goodbye"))
|
778
623
|
|
779
|
-
|
780
|
-
setup do
|
781
|
-
@user = User.create(:email => "foo")
|
782
|
-
end
|
624
|
+
assert ["3", "2"] == @post.related.map { |model| model.id }
|
783
625
|
|
784
|
-
|
785
|
-
assert_equal @user, User[@user.id]
|
626
|
+
assert "3" == @post.related.shift.id
|
786
627
|
|
787
|
-
|
788
|
-
assert_not_equal User.new, User.new
|
789
|
-
end
|
628
|
+
assert "2" == @post.related.pop.id
|
790
629
|
|
791
|
-
|
792
|
-
|
793
|
-
end
|
630
|
+
assert @post.related.pop.nil?
|
631
|
+
end
|
794
632
|
|
795
|
-
|
796
|
-
|
797
|
-
assert_not_equal @user, true
|
633
|
+
# Applying arbitrary transformations
|
634
|
+
require "date"
|
798
635
|
|
799
|
-
|
800
|
-
|
801
|
-
|
636
|
+
class MyActiveRecordModel
|
637
|
+
def self.find(id)
|
638
|
+
return new if id.to_i == 1
|
802
639
|
end
|
803
640
|
|
804
|
-
|
805
|
-
|
806
|
-
|
807
|
-
counter :visits
|
808
|
-
set :friends, self
|
809
|
-
list :comments, self
|
810
|
-
|
811
|
-
def foo
|
812
|
-
bar.foo
|
813
|
-
end
|
814
|
-
|
815
|
-
def baz
|
816
|
-
bar.new.foo
|
817
|
-
end
|
641
|
+
def id
|
642
|
+
1
|
643
|
+
end
|
818
644
|
|
819
|
-
|
820
|
-
|
821
|
-
|
822
|
-
|
645
|
+
def ==(other)
|
646
|
+
id == other.id
|
647
|
+
end
|
648
|
+
end
|
823
649
|
|
824
|
-
|
825
|
-
|
650
|
+
class ::Calendar < Ohm::Model
|
651
|
+
list :holidays, lambda { |v| Date.parse(v) }
|
652
|
+
list :subscribers, lambda { |id| MyActiveRecordModel.find(id) }
|
653
|
+
list :appointments, Appointment
|
654
|
+
end
|
826
655
|
|
827
|
-
|
656
|
+
class ::Appointment < Ohm::Model
|
657
|
+
attribute :text
|
658
|
+
reference :subscriber, lambda { |id| MyActiveRecordModel.find(id) }
|
659
|
+
end
|
828
660
|
|
829
|
-
|
830
|
-
|
831
|
-
bar.friends << Bar.create
|
832
|
-
bar.comments << Bar.create
|
833
|
-
bar.incr(:visits)
|
661
|
+
setup do
|
662
|
+
@calendar = Calendar.create
|
834
663
|
|
835
|
-
|
836
|
-
|
664
|
+
@calendar.holidays.key.rpush "2009-05-25"
|
665
|
+
@calendar.holidays.key.rpush "2009-07-09"
|
837
666
|
|
838
|
-
|
839
|
-
|
840
|
-
block.call
|
841
|
-
rescue NoMethodError => exception_raised
|
842
|
-
end
|
667
|
+
@calendar.subscribers << MyActiveRecordModel.find(1)
|
668
|
+
end
|
843
669
|
|
844
|
-
|
845
|
-
|
670
|
+
test "apply a transformation" do
|
671
|
+
assert [Date.new(2009, 5, 25), Date.new(2009, 7, 9)] == @calendar.holidays.all
|
846
672
|
|
847
|
-
|
848
|
-
|
849
|
-
|
673
|
+
assert [1] == @calendar.subscribers.all.map { |model| model.id }
|
674
|
+
assert [MyActiveRecordModel.find(1)] == @calendar.subscribers.all
|
675
|
+
end
|
850
676
|
|
851
|
-
|
852
|
-
|
853
|
-
|
854
|
-
|
677
|
+
test "allow lambdas in references" do
|
678
|
+
appointment = Appointment.create(:subscriber => MyActiveRecordModel.find(1))
|
679
|
+
assert MyActiveRecordModel.find(1) == appointment.subscriber
|
680
|
+
end
|
855
681
|
|
856
|
-
|
857
|
-
|
858
|
-
attribute :name
|
682
|
+
test "work with models too" do
|
683
|
+
@calendar.appointments.add(Appointment.create(:text => "Meet with Bertrand"))
|
859
684
|
|
860
|
-
|
861
|
-
|
862
|
-
super
|
863
|
-
end
|
864
|
-
end
|
685
|
+
assert [Appointment[1]] == Calendar[1].appointments.sort
|
686
|
+
end
|
865
687
|
|
866
|
-
|
867
|
-
|
868
|
-
|
869
|
-
|
870
|
-
|
871
|
-
|
872
|
-
|
873
|
-
end
|
874
|
-
end
|
688
|
+
# Sorting lists and sets
|
689
|
+
setup do
|
690
|
+
@post = Post.create(:body => "Lorem")
|
691
|
+
@post.related << Post.create
|
692
|
+
@post.related << Post.create
|
693
|
+
@post.related << Post.create
|
694
|
+
end
|
875
695
|
|
876
|
-
|
877
|
-
|
878
|
-
|
879
|
-
reference :source, Post
|
880
|
-
collection :comments, Comment
|
881
|
-
list :ratings, Rating
|
882
|
-
end
|
696
|
+
test "sort values" do
|
697
|
+
assert %w{2 3 4} == @post.related.sort.map { |model| model.id }
|
698
|
+
end
|
883
699
|
|
884
|
-
|
885
|
-
|
886
|
-
|
700
|
+
# Sorting lists and sets by model attributes
|
701
|
+
setup do
|
702
|
+
@event = Event.create(:name => "Ruby Tuesday")
|
703
|
+
@event.attendees << Person.create(:name => "D")
|
704
|
+
@event.attendees << Person.create(:name => "C")
|
705
|
+
@event.attendees << Person.create(:name => "B")
|
706
|
+
@event.attendees << Person.create(:name => "A")
|
707
|
+
end
|
887
708
|
|
888
|
-
|
889
|
-
|
890
|
-
|
709
|
+
test "sort the model instances by the values provided" do
|
710
|
+
people = @event.attendees.sort_by(:name, :order => "ALPHA")
|
711
|
+
assert %w[A B C D] == people.map { |person| person.name }
|
712
|
+
end
|
891
713
|
|
892
|
-
|
893
|
-
|
894
|
-
|
895
|
-
|
714
|
+
test "accept a number in the limit parameter" do
|
715
|
+
people = @event.attendees.sort_by(:name, :limit => 2, :order => "ALPHA")
|
716
|
+
assert %w[A B] == people.map { |person| person.name }
|
717
|
+
end
|
896
718
|
|
897
|
-
|
898
|
-
|
899
|
-
|
900
|
-
|
901
|
-
end
|
719
|
+
test "use the start parameter as an offset if the limit is provided" do
|
720
|
+
people = @event.attendees.sort_by(:name, :limit => 2, :start => 1, :order => "ALPHA")
|
721
|
+
assert %w[B C] == people.map { |person| person.name }
|
722
|
+
end
|
902
723
|
|
903
|
-
|
904
|
-
|
905
|
-
|
724
|
+
# Collections initialized with a Model parameter
|
725
|
+
setup do
|
726
|
+
@user = User.create(:email => "albert@example.com")
|
727
|
+
@user.posts.add Post.create(:body => "D")
|
728
|
+
@user.posts.add Post.create(:body => "C")
|
729
|
+
@user.posts.add Post.create(:body => "B")
|
730
|
+
@user.posts.add Post.create(:body => "A")
|
731
|
+
end
|
906
732
|
|
907
|
-
|
908
|
-
|
909
|
-
|
910
|
-
@post.save
|
911
|
-
assert_equal "Albert", Post[@post.id].author.name
|
912
|
-
end
|
733
|
+
test "return instances of the passed model" do
|
734
|
+
assert Post == @user.posts.first.class
|
735
|
+
end
|
913
736
|
|
914
|
-
|
915
|
-
|
916
|
-
|
917
|
-
|
918
|
-
end
|
737
|
+
# Counters
|
738
|
+
setup do
|
739
|
+
@event = Event.create(:name => "Ruby Tuesday")
|
740
|
+
end
|
919
741
|
|
920
|
-
|
921
|
-
|
922
|
-
|
923
|
-
|
924
|
-
|
742
|
+
test "raise ArgumentError if the attribute is not a counter" do
|
743
|
+
assert_raise ArgumentError do
|
744
|
+
@event.incr(:name)
|
745
|
+
end
|
746
|
+
end
|
925
747
|
|
926
|
-
|
927
|
-
|
928
|
-
|
748
|
+
test "be zero if not initialized" do
|
749
|
+
assert 0 == @event.votes
|
750
|
+
end
|
929
751
|
|
930
|
-
|
931
|
-
|
752
|
+
test "be able to increment a counter" do
|
753
|
+
@event.incr(:votes)
|
754
|
+
assert 1 == @event.votes
|
932
755
|
|
933
|
-
|
756
|
+
@event.incr(:votes, 2)
|
757
|
+
assert 3 == @event.votes
|
758
|
+
end
|
934
759
|
|
935
|
-
|
936
|
-
|
760
|
+
test "be able to decrement a counter" do
|
761
|
+
@event.decr(:votes)
|
762
|
+
assert @event.votes == -1
|
937
763
|
|
938
|
-
|
764
|
+
@event.decr(:votes, 2)
|
765
|
+
assert @event.votes == -3
|
766
|
+
end
|
939
767
|
|
940
|
-
|
941
|
-
|
942
|
-
|
768
|
+
# Comparison
|
769
|
+
setup do
|
770
|
+
@user = User.create(:email => "foo")
|
771
|
+
end
|
943
772
|
|
944
|
-
|
945
|
-
|
946
|
-
@note = Note.create(:content => "Interesting stuff", :source => @post)
|
947
|
-
@comment = Comment.create(:note => @note)
|
948
|
-
end
|
773
|
+
test "be comparable to other instances" do
|
774
|
+
assert @user == User[@user.id]
|
949
775
|
|
950
|
-
|
951
|
-
|
952
|
-
|
953
|
-
end
|
776
|
+
assert @user != User.create
|
777
|
+
assert User.new != User.new
|
778
|
+
end
|
954
779
|
|
955
|
-
|
956
|
-
|
957
|
-
|
780
|
+
test "not be comparable to instances of other models" do
|
781
|
+
assert @user != Event.create(:name => "Ruby Tuesday")
|
782
|
+
end
|
958
783
|
|
959
|
-
|
960
|
-
|
961
|
-
|
784
|
+
test "be comparable to non-models" do
|
785
|
+
assert @user != 1
|
786
|
+
assert @user != true
|
962
787
|
|
963
|
-
|
964
|
-
|
788
|
+
# Not equal although the other object responds to #key.
|
789
|
+
assert @user != OpenStruct.new(:key => @user.send(:key))
|
790
|
+
end
|
965
791
|
|
966
|
-
|
967
|
-
|
792
|
+
# Debugging
|
793
|
+
class ::Bar < Ohm::Model
|
794
|
+
attribute :name
|
795
|
+
counter :visits
|
796
|
+
set :friends, self
|
797
|
+
list :comments, self
|
968
798
|
|
969
|
-
|
970
|
-
|
971
|
-
end
|
799
|
+
def foo
|
800
|
+
bar.foo
|
972
801
|
end
|
973
802
|
|
974
|
-
|
975
|
-
|
976
|
-
|
977
|
-
end
|
978
|
-
|
979
|
-
class ::Make < Ohm::Model
|
980
|
-
attribute :name
|
981
|
-
end
|
803
|
+
def baz
|
804
|
+
bar.new.foo
|
805
|
+
end
|
982
806
|
|
983
|
-
|
984
|
-
|
985
|
-
|
986
|
-
|
807
|
+
def bar
|
808
|
+
SomeMissingConstant
|
809
|
+
end
|
810
|
+
end
|
987
811
|
|
988
|
-
|
989
|
-
|
990
|
-
make = Make.create(:name => "Renault")
|
812
|
+
test "provide a meaningful inspect" do
|
813
|
+
bar = Bar.new
|
991
814
|
|
992
|
-
|
993
|
-
assert_equal [], Redis.connect.smembers("Car:all")
|
815
|
+
assert "#<Bar:? name=nil friends=nil comments=nil visits=0>" == bar.inspect
|
994
816
|
|
995
|
-
|
996
|
-
|
817
|
+
bar.update(:name => "Albert")
|
818
|
+
bar.friends << Bar.create
|
819
|
+
bar.comments << Bar.create
|
820
|
+
bar.incr(:visits)
|
997
821
|
|
998
|
-
|
999
|
-
|
822
|
+
assert %Q{#<Bar:#{bar.id} name="Albert" friends=#<Set (Bar): ["2"]> comments=#<List (Bar): ["3"]> visits=1>} == Bar[bar.id].inspect
|
823
|
+
end
|
1000
824
|
|
1001
|
-
|
825
|
+
def assert_wrapper_exception(&block)
|
826
|
+
begin
|
827
|
+
block.call
|
828
|
+
rescue NoMethodError => exception_raised
|
829
|
+
end
|
1002
830
|
|
1003
|
-
|
1004
|
-
|
1005
|
-
|
831
|
+
assert exception_raised.message =~
|
832
|
+
/You tried to call SomeMissingConstant#\w+, but SomeMissingConstant is not defined on #{__FILE__}:\d+:in `bar'/
|
833
|
+
end
|
1006
834
|
|
1007
|
-
|
1008
|
-
|
835
|
+
test "inform about a miscatch by Wrapper when calling class methods" do
|
836
|
+
assert_wrapper_exception { Bar.new.baz }
|
837
|
+
end
|
1009
838
|
|
1010
|
-
|
839
|
+
test "inform about a miscatch by Wrapper when calling instance methods" do
|
840
|
+
assert_wrapper_exception { Bar.new.foo }
|
841
|
+
end
|
1011
842
|
|
1012
|
-
|
1013
|
-
|
843
|
+
# Overwriting write
|
844
|
+
class ::Baz < Ohm::Model
|
845
|
+
attribute :name
|
1014
846
|
|
1015
|
-
|
1016
|
-
|
1017
|
-
|
847
|
+
def write
|
848
|
+
self.name = "Foobar"
|
849
|
+
super
|
1018
850
|
end
|
851
|
+
end
|
1019
852
|
|
1020
|
-
|
1021
|
-
|
1022
|
-
|
1023
|
-
|
853
|
+
test "work properly" do
|
854
|
+
baz = Baz.new
|
855
|
+
baz.name = "Foo"
|
856
|
+
baz.save
|
857
|
+
baz.name = "Foo"
|
858
|
+
baz.save
|
859
|
+
assert "Foobar" == Baz[baz.id].name
|
860
|
+
end
|
1024
861
|
|
1025
|
-
|
862
|
+
# Models connected to different databases
|
863
|
+
class ::Car < Ohm::Model
|
864
|
+
attribute :name
|
865
|
+
end
|
1026
866
|
|
1027
|
-
|
1028
|
-
|
1029
|
-
|
867
|
+
class ::Make < Ohm::Model
|
868
|
+
attribute :name
|
869
|
+
end
|
1030
870
|
|
1031
|
-
|
1032
|
-
|
1033
|
-
|
1034
|
-
|
871
|
+
setup do
|
872
|
+
Car.connect(:db => 15)
|
873
|
+
Car.db.flushdb
|
874
|
+
end
|
1035
875
|
|
1036
|
-
|
1037
|
-
|
1038
|
-
|
876
|
+
test "save to the selected database" do
|
877
|
+
car = Car.create(:name => "Twingo")
|
878
|
+
make = Make.create(:name => "Renault")
|
1039
879
|
|
1040
|
-
|
1041
|
-
|
1042
|
-
end
|
1043
|
-
end
|
880
|
+
assert ["1"] == Redis.connect.smembers("Make:all")
|
881
|
+
assert [] == Redis.connect.smembers("Car:all")
|
1044
882
|
|
1045
|
-
|
1046
|
-
|
1047
|
-
person = Venue.new
|
1048
|
-
assert_equal({}, person.to_hash)
|
1049
|
-
end
|
1050
|
-
end
|
883
|
+
assert ["1"] == Car.db.smembers("Car:all")
|
884
|
+
assert [] == Car.db.smembers("Make:all")
|
1051
885
|
|
1052
|
-
|
1053
|
-
|
1054
|
-
person = Venue.new
|
1055
|
-
person.valid?
|
886
|
+
assert car == Car[1]
|
887
|
+
assert make == Make[1]
|
1056
888
|
|
1057
|
-
|
1058
|
-
end
|
1059
|
-
end
|
889
|
+
Make.db.flushdb
|
1060
890
|
|
1061
|
-
|
1062
|
-
|
1063
|
-
|
1064
|
-
assert_equal({ :id => '1' }, person.to_hash)
|
1065
|
-
end
|
1066
|
-
end
|
891
|
+
assert car == Car[1]
|
892
|
+
assert Make[1].nil?
|
893
|
+
end
|
1067
894
|
|
1068
|
-
|
1069
|
-
|
1070
|
-
person = Venue.create(:name => "John Doe")
|
1071
|
-
person.name = nil
|
1072
|
-
person.valid?
|
895
|
+
test "allow changing the database" do
|
896
|
+
Car.create(:name => "Twingo")
|
1073
897
|
|
1074
|
-
|
898
|
+
assert ["1"] == Car.all.key.smembers
|
1075
899
|
|
1076
|
-
|
1077
|
-
|
1078
|
-
end
|
900
|
+
Car.connect
|
901
|
+
assert [] == Car.all.key.smembers
|
1079
902
|
|
1080
|
-
|
1081
|
-
|
903
|
+
Car.connect :db => 15
|
904
|
+
assert ["1"] == Car.all.key.smembers
|
905
|
+
end
|
1082
906
|
|
1083
|
-
|
1084
|
-
|
1085
|
-
|
907
|
+
# Persistence
|
908
|
+
test "persist attributes to a hash" do
|
909
|
+
event = Event.create(:name => "Redis Meetup")
|
910
|
+
event.incr(:votes)
|
1086
911
|
|
1087
|
-
|
1088
|
-
super.merge(:language => language)
|
1089
|
-
end
|
1090
|
-
end
|
912
|
+
assert "hash" == Ohm.redis.type("Event:1")
|
1091
913
|
|
1092
|
-
|
1093
|
-
|
1094
|
-
|
1095
|
-
expected_hash = { :id => '1', :language => 'Ruby' }
|
914
|
+
assert [
|
915
|
+
"Event:1", "Event:all", "Event:id"
|
916
|
+
].sort == Ohm.redis.keys("Event:*").sort
|
1096
917
|
|
1097
|
-
|
1098
|
-
|
1099
|
-
|
918
|
+
assert "Redis Meetup" == Event[1].name
|
919
|
+
assert 1 == Event[1].votes
|
920
|
+
end
|
1100
921
|
|
1101
|
-
|
1102
|
-
|
1103
|
-
|
922
|
+
# a Model with individual attribute writing needs
|
923
|
+
class Order < Ohm::Model
|
924
|
+
attribute :state
|
1104
925
|
|
1105
|
-
|
1106
|
-
|
1107
|
-
assert_equal "Ruby", json["language"]
|
1108
|
-
end
|
1109
|
-
end
|
926
|
+
def authorize!
|
927
|
+
write_remote :state, 'authorized'
|
1110
928
|
end
|
929
|
+
end
|
1111
930
|
|
1112
|
-
|
1113
|
-
|
1114
|
-
|
1115
|
-
|
1116
|
-
|
1117
|
-
write_remote :state, 'authorized'
|
1118
|
-
end
|
1119
|
-
end
|
1120
|
-
|
1121
|
-
test "writes locally" do
|
1122
|
-
order = Order.create(:state => "pending")
|
1123
|
-
order.authorize!
|
1124
|
-
assert_equal 'authorized', order.state
|
1125
|
-
end
|
931
|
+
test "writes locally" do
|
932
|
+
order = Order.create(:state => "pending")
|
933
|
+
order.authorize!
|
934
|
+
assert 'authorized' == order.state
|
935
|
+
end
|
1126
936
|
|
1127
|
-
|
1128
|
-
|
1129
|
-
|
1130
|
-
|
1131
|
-
|
1132
|
-
|
1133
|
-
end
|
937
|
+
test "writes remotely" do
|
938
|
+
order = Order.create(:state => "pending")
|
939
|
+
order.authorize!
|
940
|
+
order = Order[order.id]
|
941
|
+
assert 'authorized' == order.state
|
942
|
+
end
|
1134
943
|
|
1135
|
-
|
1136
|
-
|
1137
|
-
|
944
|
+
# namespaced models
|
945
|
+
test "be persisted" do
|
946
|
+
SomeNamespace::Foo.create(:name => "foo")
|
1138
947
|
|
1139
|
-
|
948
|
+
assert "hash" == Ohm.redis.type("SomeNamespace::Foo:1")
|
1140
949
|
|
1141
|
-
|
1142
|
-
end
|
1143
|
-
end
|
950
|
+
assert "foo" == SomeNamespace::Foo[1].name
|
1144
951
|
end
|