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.
Files changed (4) hide show
  1. data/lib/ohm.rb +63 -17
  2. data/test/model_test.rb +20 -0
  3. data/test/redis_test.rb +74 -52
  4. 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
- define_method(name) do
372
- read_local(name)
373
- end
371
+ unless attributes.include?(name)
374
372
 
375
- define_method(:"#{name}=") do |value|
376
- write_local(name, value)
377
- end
373
+ define_method(name) do
374
+ read_local(name)
375
+ end
378
376
 
379
- attributes << name
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
- define_method(name) do
388
- read_local(name).to_i
389
- end
390
+ unless counters.include?(name)
391
+
392
+ define_method(name) do
393
+ read_local(name).to_i
394
+ end
390
395
 
391
- counters << name
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
- attr_list_reader(name, model)
400
- collections << name
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
- attr_set_reader(name, model)
410
- collections << name
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 << att
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
@@ -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
@@ -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
- @r.mset(:foo => "foobar", :bar => 1000)
45
- assert_equal ["foobar", "1000"], @r.mget("foo", "bar")
46
- assert_equal ["foobar", "1000", nil], @r.mget("foo", "bar", "baz")
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
- @r.rpush "list", 'one'
228
- @r.rpush "list", 'two'
229
- @r.rpush "list", 'three'
230
- assert_equal "list", @r.type('list')
231
- assert_equal 3, @r.llen('list')
232
- assert_equal %w(one two three), @r.lrange('list',0,-1)
233
- assert_equal [], @r.lrange('tmp',0,-1)
234
- assert_equal "three", @r.rpoplpush('list', 'tmp')
235
- assert_equal %w(three), @r.lrange('tmp',0,-1)
236
- assert_equal "two", @r.rpoplpush('list', 'tmp')
237
- assert_equal %w(two three), @r.lrange('tmp',0,-1)
238
- assert_equal "one", @r.rpoplpush('list', 'tmp')
239
- assert_equal %w(one two three), @r.lrange('tmp',0,-1)
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
- @r.zadd 'zset', 1, 'set'
314
- assert_equal %w(set), @r.zrange('zset', 0, 1)
315
- assert_equal 1, @r.zcard('zset')
316
- @r.del('zset')
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
- @r.zadd 'zset', 1, 'foo'
321
- @r.zcard('zset')
322
- @r.del('zset')
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
- @r.zadd 'zset', 1, 'set'
328
- assert_equal 1, @r.zcard('zset')
329
- @r.zadd 'zset', 2, 'set2'
330
- assert_equal 2, @r.zcard('zset')
331
- @r.zrem 'zset', 'set'
332
- assert_equal 1, @r.zcard('zset')
333
- @r.del('zset')
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
- @r.zadd 'zset', 1, 'set'
338
- @r.zadd 'zset', 2, 'set2'
339
- @r.zadd 'zset', 3, 'set3'
340
- assert_equal 3, @r.zcard('zset')
341
- assert_equal %w(set set2 set3), @r.zrange('zset', 0, 3)
342
- @r.del('set')
343
- @r.del('set2')
344
- @r.del('set3')
345
- @r.del('zset')
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
- @r.zadd 'zset', 1, 'set'
350
- @r.zadd 'zset', 2, 'set2'
351
- @r.zadd 'zset', 3, 'set3'
352
- assert_equal 3, @r.zcard('zset')
353
- assert_equal %w(set3 set2 set), @r.zrevrange('zset', 0, 3)
354
- @r.del('zset')
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
- @r.zadd 'zset', 1, 'set'
359
- @r.zadd 'zset', 2, 'set2'
360
- @r.zadd 'zset', 3, 'set3'
361
- @r.zadd 'zset', 4, 'set4'
362
- assert_equal 4, @r.zcard('zset')
363
- assert_equal %w(set2 set3), @r.zrangebyscore('zset', 2, 3)
364
- @r.del('zset')
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
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ohm
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.28
4
+ version: 0.0.29
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michel Martens