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 +3 -1
- data/VERSION +1 -1
- data/lib/remodel/caching_context.rb +20 -5
- data/lib/remodel/context.rb +12 -0
- data/lib/remodel.rb +2 -0
- data/test/test_caching_context.rb +54 -0
- metadata +3 -3
data/README.md
CHANGED
@@ -66,7 +66,9 @@ now you can do:
|
|
66
66
|
|
67
67
|
>> require './example/book'
|
68
68
|
=> true
|
69
|
-
>>
|
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.
|
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
|
-
|
38
|
-
@cache[field] =
|
39
|
-
|
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
|
data/lib/remodel/context.rb
CHANGED
@@ -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
|
-
-
|
9
|
-
version: 0.4.
|
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-
|
17
|
+
date: 2011-07-26 00:00:00 +02:00
|
18
18
|
default_executable:
|
19
19
|
dependencies: []
|
20
20
|
|