remodel 0.4.0 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.md CHANGED
@@ -66,7 +66,9 @@ now you can do:
66
66
 
67
67
  >> require './example/book'
68
68
  => true
69
- >> book = Book.create 'shelf', :title => 'Moby Dick', :year => 1851
69
+ >> context = Remodel.create_context('shelf')
70
+ => #<Remodel::Context(shelf)>
71
+ >> book = Book.create context, :title => 'Moby Dick', :year => 1851
70
72
  => #<Book(shelf, 1) title: "Moby Dick", year: 1851, author: "(anonymous)">
71
73
  >> chapter = book.chapters.create :title => 'Ishmael'
72
74
  => #<Chapter(shelf, 1) title: "Ishmael">
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.4.0
1
+ 0.4.1
@@ -17,6 +17,20 @@ module Remodel
17
17
  @context.key
18
18
  end
19
19
 
20
+ def batched
21
+ raise InvalidUse, "cannot nest batched blocks" if @dirty
22
+ begin
23
+ @dirty = Set.new
24
+ yield
25
+ ensure
26
+ to_delete = @dirty.select { |field| @cache[field].nil? }
27
+ to_update = (@dirty - to_delete).to_a
28
+ @context.hmset(*to_update.zip(@cache.values_at(*to_update)).flatten)
29
+ @context.hmdel(*to_delete)
30
+ @dirty = nil
31
+ end
32
+ end
33
+
20
34
  def hget(field)
21
35
  @cache[field] = @context.hget(field) unless @cache.has_key?(field)
22
36
  @cache[field]
@@ -30,18 +44,19 @@ module Remodel
30
44
  def hset(field, value)
31
45
  value = value.to_s if value
32
46
  @cache[field] = value
33
- @context.hset(field, value)
47
+ @dirty ? @dirty.add(field) : @context.hset(field, value)
34
48
  end
35
49
 
36
50
  def hincrby(field, value)
37
- result = @context.hincrby(field, value)
38
- @cache[field] = result.to_s
39
- result
51
+ new_value = @dirty ? hget(field).to_i + value : @context.hincrby(field, value)
52
+ @cache[field] = new_value.to_s
53
+ @dirty.add(field) if @dirty
54
+ new_value
40
55
  end
41
56
 
42
57
  def hdel(field)
43
58
  @cache[field] = nil
44
- @context.hdel(field)
59
+ @dirty ? @dirty.add(field) : @context.hdel(field)
45
60
  end
46
61
 
47
62
  def inspect
@@ -25,6 +25,11 @@ module Remodel
25
25
  Remodel.redis.hset(@key, field, value)
26
26
  end
27
27
 
28
+ def hmset(*fields_and_values)
29
+ return if fields_and_values.empty?
30
+ Remodel.redis.hmset(@key, *fields_and_values)
31
+ end
32
+
28
33
  def hincrby(field, value)
29
34
  Remodel.redis.hincrby(@key, field, value)
30
35
  end
@@ -33,6 +38,13 @@ module Remodel
33
38
  Remodel.redis.hdel(@key, field)
34
39
  end
35
40
 
41
+ def hmdel(*fields)
42
+ return if fields.empty?
43
+ Remodel.redis.pipelined do
44
+ fields.each { |field| Remodel.redis.hdel(@key, field) }
45
+ end
46
+ end
47
+
36
48
  def inspect
37
49
  "\#<#{self.class.name}(#{@key})>"
38
50
  end
data/lib/remodel.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  require 'rubygems'
2
2
  require 'redis'
3
3
  require 'date'
4
+ require 'set'
4
5
 
5
6
  # If available, use the superfast YAJL lib to parse JSON.
6
7
  begin
@@ -37,6 +38,7 @@ module Remodel
37
38
  class InvalidKeyPrefix < Error; end
38
39
  class InvalidType < Error; end
39
40
  class MissingContext < Error; end
41
+ class InvalidUse < Error; end
40
42
 
41
43
  # By default, the redis server is expected to listen at `localhost:6379`.
42
44
  # Otherwise you will have to set `Remodel.redis` to a suitably initialized
@@ -111,6 +111,60 @@ class TestCachingContext < Test::Unit::TestCase
111
111
  assert @cache.cache.has_key?('x')
112
112
  end
113
113
  end
114
+
115
+ context 'batched' do
116
+ should "ensure batched blocks are not nested" do
117
+ assert_raise(Remodel::InvalidUse) do
118
+ @cache.batched do
119
+ @cache.batched do
120
+ end
121
+ end
122
+ end
123
+ end
124
+
125
+ should "collect hset calls into one hmset" do
126
+ context.expects(:hset).never
127
+ context.expects(:hmset).with('a', '3', 'b', '2') #might break in ruby 1.8
128
+ @cache.batched do
129
+ @cache.hset('a', 1)
130
+ @cache.hset('b', 2)
131
+ @cache.hset('a', 3)
132
+ end
133
+ end
134
+
135
+ should "collect hdel calls into one hmdel" do
136
+ context.expects(:hdel).never
137
+ context.expects(:hmdel).with('a', 'b')
138
+ @cache.batched do
139
+ @cache.hdel('a')
140
+ @cache.hdel('b')
141
+ @cache.hdel('a')
142
+ end
143
+ end
144
+
145
+ should "handle multiple hset and hdel to the same field" do
146
+ context.expects(:hset).never
147
+ context.expects(:hdel).never
148
+ context.expects(:hmset).with('a', '3')
149
+ context.expects(:hmdel).with()
150
+ @cache.batched do
151
+ @cache.hset('a', 1)
152
+ @cache.hdel('a')
153
+ @cache.hset('a', 3)
154
+ end
155
+ end
156
+
157
+ should "handle hincrby" do
158
+ context.expects(:hset).never
159
+ context.expects(:hmset).with('i', '2')
160
+ @cache.batched do
161
+ @cache.hdel('i')
162
+ @cache.hincrby('i', 1)
163
+ @cache.hincrby('i', 1)
164
+ end
165
+ end
166
+ end
167
+
114
168
  end
115
169
 
116
170
  end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 4
8
- - 0
9
- version: 0.4.0
8
+ - 1
9
+ version: 0.4.1
10
10
  platform: ruby
11
11
  authors:
12
12
  - Tim Lossen
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2011-07-05 00:00:00 +02:00
17
+ date: 2011-07-26 00:00:00 +02:00
18
18
  default_executable:
19
19
  dependencies: []
20
20