ohm 0.0.28 → 0.0.29
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/ohm.rb +63 -17
- data/test/model_test.rb +20 -0
- data/test/redis_test.rb +74 -52
- metadata +1 -1
data/lib/ohm.rb
CHANGED
@@ -368,15 +368,18 @@ module Ohm
|
|
368
368
|
#
|
369
369
|
# @param name [Symbol] Name of the attribute.
|
370
370
|
def self.attribute(name)
|
371
|
-
|
372
|
-
read_local(name)
|
373
|
-
end
|
371
|
+
unless attributes.include?(name)
|
374
372
|
|
375
|
-
|
376
|
-
|
377
|
-
|
373
|
+
define_method(name) do
|
374
|
+
read_local(name)
|
375
|
+
end
|
378
376
|
|
379
|
-
|
377
|
+
define_method(:"#{name}=") do |value|
|
378
|
+
write_local(name, value)
|
379
|
+
end
|
380
|
+
|
381
|
+
attributes << name
|
382
|
+
end
|
380
383
|
end
|
381
384
|
|
382
385
|
# Defines a counter attribute for the model. This attribute can't be assigned, only incremented
|
@@ -384,11 +387,14 @@ module Ohm
|
|
384
387
|
#
|
385
388
|
# @param name [Symbol] Name of the counter.
|
386
389
|
def self.counter(name)
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
+
unless counters.include?(name)
|
391
|
+
|
392
|
+
define_method(name) do
|
393
|
+
read_local(name).to_i
|
394
|
+
end
|
390
395
|
|
391
|
-
|
396
|
+
counters << name
|
397
|
+
end
|
392
398
|
end
|
393
399
|
|
394
400
|
# Defines a list attribute for the model. It can be accessed only after the model instance
|
@@ -396,8 +402,10 @@ module Ohm
|
|
396
402
|
#
|
397
403
|
# @param name [Symbol] Name of the list.
|
398
404
|
def self.list(name, model = nil)
|
399
|
-
|
400
|
-
|
405
|
+
unless collections.include?(name)
|
406
|
+
attr_list_reader(name, model)
|
407
|
+
collections << name
|
408
|
+
end
|
401
409
|
end
|
402
410
|
|
403
411
|
# Defines a set attribute for the model. It can be accessed only after the model instance
|
@@ -406,8 +414,10 @@ module Ohm
|
|
406
414
|
#
|
407
415
|
# @param name [Symbol] Name of the set.
|
408
416
|
def self.set(name, model = nil)
|
409
|
-
|
410
|
-
|
417
|
+
unless collections.include?(name)
|
418
|
+
attr_set_reader(name, model)
|
419
|
+
collections << name
|
420
|
+
end
|
411
421
|
end
|
412
422
|
|
413
423
|
# Creates an index (a set) that will be used for finding instances.
|
@@ -426,7 +436,9 @@ module Ohm
|
|
426
436
|
#
|
427
437
|
# @param name [Symbol] Name of the attribute to be indexed.
|
428
438
|
def self.index(att)
|
429
|
-
indices
|
439
|
+
unless indices.include?(att)
|
440
|
+
indices << att
|
441
|
+
end
|
430
442
|
end
|
431
443
|
|
432
444
|
def self.attr_list_reader(name, model = nil)
|
@@ -609,10 +621,37 @@ module Ohm
|
|
609
621
|
self.class.key(id, *args)
|
610
622
|
end
|
611
623
|
|
624
|
+
# Rewrite at runtime to use either SET or MSET for persisting to
|
625
|
+
# Redis. The idea is to use MSET when possible.
|
612
626
|
def write
|
627
|
+
if legacy_redis_version?
|
628
|
+
def write
|
629
|
+
write_with_set
|
630
|
+
end
|
631
|
+
else
|
632
|
+
def write
|
633
|
+
write_with_mset
|
634
|
+
end
|
635
|
+
end
|
636
|
+
write
|
637
|
+
end
|
638
|
+
|
639
|
+
# Write attributes using SET
|
640
|
+
# This method will be removed once MSET becomes standard.
|
641
|
+
def write_with_set
|
642
|
+
attributes.each do |att|
|
643
|
+
(value = send(att)) ?
|
644
|
+
db.set(key(att), value) :
|
645
|
+
db.del(key(att))
|
646
|
+
end
|
647
|
+
end
|
648
|
+
|
649
|
+
# Write attributes using MSET
|
650
|
+
# This is the preferred method, and will be the only option
|
651
|
+
# available once MSET becomes standard.
|
652
|
+
def write_with_mset
|
613
653
|
unless attributes.empty?
|
614
654
|
rems, adds = attributes.map { |a| [key(a), send(a)] }.partition { |t| t.last.nil? }
|
615
|
-
|
616
655
|
db.del(*rems.flatten.compact) unless rems.empty?
|
617
656
|
db.mset(adds.flatten) unless adds.empty?
|
618
657
|
end
|
@@ -620,6 +659,13 @@ module Ohm
|
|
620
659
|
|
621
660
|
private
|
622
661
|
|
662
|
+
# Determine if MSET is available. This method
|
663
|
+
# and the branch at #write will be deprecated
|
664
|
+
# once Redis 1.1 becomes the recommended version.
|
665
|
+
def legacy_redis_version?
|
666
|
+
db.info[:redis_version] <= "1.02"
|
667
|
+
end
|
668
|
+
|
623
669
|
def self.db
|
624
670
|
Ohm.redis
|
625
671
|
end
|
data/test/model_test.rb
CHANGED
@@ -626,4 +626,24 @@ class TestRedis < Test::Unit::TestCase
|
|
626
626
|
assert_equal %Q{#<Bar:#{bar.id} name="Albert" friends=#<Set: ["1", "2"]> comments=#<List: ["A"]> visits=1>}, Bar[bar.id].inspect
|
627
627
|
end
|
628
628
|
end
|
629
|
+
|
630
|
+
context "Overwritting write" do
|
631
|
+
class ::Baz < Ohm::Model
|
632
|
+
attribute :name
|
633
|
+
|
634
|
+
def write
|
635
|
+
self.name = "Foobar"
|
636
|
+
super
|
637
|
+
end
|
638
|
+
end
|
639
|
+
|
640
|
+
should "work properly" do
|
641
|
+
baz = Baz.new
|
642
|
+
baz.name = "Foo"
|
643
|
+
baz.save
|
644
|
+
baz.name = "Foo"
|
645
|
+
baz.save
|
646
|
+
assert_equal "Foobar", Baz[baz.id].name
|
647
|
+
end
|
648
|
+
end
|
629
649
|
end
|
data/test/redis_test.rb
CHANGED
@@ -14,6 +14,12 @@ class Foo
|
|
14
14
|
end
|
15
15
|
|
16
16
|
class RedisTest < Test::Unit::TestCase
|
17
|
+
setup do
|
18
|
+
@legacy ||= begin
|
19
|
+
Ohm.redis.info[:redis_version] <= "1.02"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
17
23
|
describe "redis" do
|
18
24
|
setup do
|
19
25
|
@r ||= Ohm.redis
|
@@ -41,9 +47,11 @@ class RedisTest < Test::Unit::TestCase
|
|
41
47
|
end
|
42
48
|
|
43
49
|
should "be able to MSET keys" do
|
44
|
-
@
|
45
|
-
|
46
|
-
|
50
|
+
unless @legacy
|
51
|
+
@r.mset(:foo => "foobar", :bar => 1000)
|
52
|
+
assert_equal ["foobar", "1000"], @r.mget("foo", "bar")
|
53
|
+
assert_equal ["foobar", "1000", nil], @r.mget("foo", "bar", "baz")
|
54
|
+
end
|
47
55
|
end
|
48
56
|
|
49
57
|
should "be able to MGET keys" do
|
@@ -224,19 +232,21 @@ class RedisTest < Test::Unit::TestCase
|
|
224
232
|
end
|
225
233
|
|
226
234
|
should "be able to pop values from a list and push them onto a temp list with RPOPLPUSH" do
|
227
|
-
@
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
235
|
+
unless @legacy
|
236
|
+
@r.rpush "list", 'one'
|
237
|
+
@r.rpush "list", 'two'
|
238
|
+
@r.rpush "list", 'three'
|
239
|
+
assert_equal "list", @r.type('list')
|
240
|
+
assert_equal 3, @r.llen('list')
|
241
|
+
assert_equal %w(one two three), @r.lrange('list',0,-1)
|
242
|
+
assert_equal [], @r.lrange('tmp',0,-1)
|
243
|
+
assert_equal "three", @r.rpoplpush('list', 'tmp')
|
244
|
+
assert_equal %w(three), @r.lrange('tmp',0,-1)
|
245
|
+
assert_equal "two", @r.rpoplpush('list', 'tmp')
|
246
|
+
assert_equal %w(two three), @r.lrange('tmp',0,-1)
|
247
|
+
assert_equal "one", @r.rpoplpush('list', 'tmp')
|
248
|
+
assert_equal %w(one two three), @r.lrange('tmp',0,-1)
|
249
|
+
end
|
240
250
|
end
|
241
251
|
|
242
252
|
should "be able add members to a set" do
|
@@ -310,58 +320,70 @@ class RedisTest < Test::Unit::TestCase
|
|
310
320
|
end
|
311
321
|
|
312
322
|
should "be able add members to a zset ZADD" do
|
313
|
-
@
|
314
|
-
|
315
|
-
|
316
|
-
|
323
|
+
unless @legacy
|
324
|
+
@r.zadd 'zset', 1, 'set'
|
325
|
+
assert_equal %w(set), @r.zrange('zset', 0, 1)
|
326
|
+
assert_equal 1, @r.zcard('zset')
|
327
|
+
@r.del('zset')
|
328
|
+
end
|
317
329
|
end
|
318
330
|
|
319
331
|
should "be able count the members of a zset ZCARD" do
|
320
|
-
@
|
321
|
-
|
322
|
-
|
332
|
+
unless @legacy
|
333
|
+
@r.zadd 'zset', 1, 'foo'
|
334
|
+
@r.zcard('zset')
|
335
|
+
@r.del('zset')
|
336
|
+
end
|
323
337
|
end
|
324
338
|
|
325
339
|
|
326
340
|
should "be able delete members of a zset ZREM" do
|
327
|
-
@
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
341
|
+
unless @legacy
|
342
|
+
@r.zadd 'zset', 1, 'set'
|
343
|
+
assert_equal 1, @r.zcard('zset')
|
344
|
+
@r.zadd 'zset', 2, 'set2'
|
345
|
+
assert_equal 2, @r.zcard('zset')
|
346
|
+
@r.zrem 'zset', 'set'
|
347
|
+
assert_equal 1, @r.zcard('zset')
|
348
|
+
@r.del('zset')
|
349
|
+
end
|
334
350
|
end
|
335
351
|
|
336
352
|
should "be able to get a range of values from a zset ZRANGE" do
|
337
|
-
@
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
353
|
+
unless @legacy
|
354
|
+
@r.zadd 'zset', 1, 'set'
|
355
|
+
@r.zadd 'zset', 2, 'set2'
|
356
|
+
@r.zadd 'zset', 3, 'set3'
|
357
|
+
assert_equal 3, @r.zcard('zset')
|
358
|
+
assert_equal %w(set set2 set3), @r.zrange('zset', 0, 3)
|
359
|
+
@r.del('set')
|
360
|
+
@r.del('set2')
|
361
|
+
@r.del('set3')
|
362
|
+
@r.del('zset')
|
363
|
+
end
|
346
364
|
end
|
347
365
|
|
348
366
|
should "be able to get a reverse range of values from a zset ZREVRANGE" do
|
349
|
-
@
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
367
|
+
unless @legacy
|
368
|
+
@r.zadd 'zset', 1, 'set'
|
369
|
+
@r.zadd 'zset', 2, 'set2'
|
370
|
+
@r.zadd 'zset', 3, 'set3'
|
371
|
+
assert_equal 3, @r.zcard('zset')
|
372
|
+
assert_equal %w(set3 set2 set), @r.zrevrange('zset', 0, 3)
|
373
|
+
@r.del('zset')
|
374
|
+
end
|
355
375
|
end
|
356
376
|
|
357
377
|
should "be able to get a range by score of values from a zset ZRANGEBYSCORE" do
|
358
|
-
@
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
378
|
+
unless @legacy
|
379
|
+
@r.zadd 'zset', 1, 'set'
|
380
|
+
@r.zadd 'zset', 2, 'set2'
|
381
|
+
@r.zadd 'zset', 3, 'set3'
|
382
|
+
@r.zadd 'zset', 4, 'set4'
|
383
|
+
assert_equal 4, @r.zcard('zset')
|
384
|
+
assert_equal %w(set2 set3), @r.zrangebyscore('zset', 2, 3)
|
385
|
+
@r.del('zset')
|
386
|
+
end
|
365
387
|
end
|
366
388
|
|
367
389
|
should "provide info" do
|