memcacheable 0.0.2 → 0.1.0
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.
- checksums.yaml +4 -4
- data/README.md +28 -3
- data/lib/memcacheable.rb +9 -0
- data/lib/memcacheable/fetch_belongs_to.rb +8 -3
- data/lib/memcacheable/fetch_has_many.rb +1 -1
- data/lib/memcacheable/fetch_has_one.rb +1 -1
- data/lib/memcacheable/fetch_method.rb +23 -0
- data/lib/memcacheable/version.rb +1 -1
- data/spec/lib/memcacheable_spec.rb +33 -2
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 83bbf521df93a4a60b8a30d553026ad529de5a4a
|
|
4
|
+
data.tar.gz: b4c06414324517d18d7baeb121340b190784d418
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 70da4d0ccb557357110e24298fc01b41995b3da99ead6ebd23d85101ea45cecfdeb26e7476d303a2e2894d5154ca3fc1cd6ea0d5900b1e4cecc3aa6376a36bd6
|
|
7
|
+
data.tar.gz: 0365dced8c66ecd9f3a9e0577a187ef7e62d9de21dc88816c7f17737943be9f7a706c5678ace823b50ae9837b17bc60c4466c046ef811e3daff5d9750d7e314b
|
data/README.md
CHANGED
|
@@ -26,7 +26,7 @@ class Person < ActiveRecord::Base
|
|
|
26
26
|
end
|
|
27
27
|
```
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
Boom! Now you can `fetch` a person by their id, like below. When the person gets updated or touched, it will flush the cache, and the person will be reloaded on the next `fetch`.
|
|
30
30
|
|
|
31
31
|
```ruby
|
|
32
32
|
person = Person.fetch id # caches the person
|
|
@@ -62,7 +62,7 @@ person = Person.fetch_by weight: 175, height: 71 # fetched and cached with new
|
|
|
62
62
|
Like noise in your life? Try `fetch_by!` (hard to say: "fetch-by-bang!").
|
|
63
63
|
|
|
64
64
|
```ruby
|
|
65
|
-
person = Person.fetch_by! name: 'Mork' # =>
|
|
65
|
+
person = Person.fetch_by! name: 'Mork' # => ActiveRecord::RecordNotFound
|
|
66
66
|
```
|
|
67
67
|
|
|
68
68
|
While `fetch_by` just pulls back just one record, you can fetch a collection with `fetch_where`:
|
|
@@ -88,7 +88,7 @@ Btw, don't do something stupid like trying to call scope methods on the result o
|
|
|
88
88
|
Person.fetch_where(height: 60).limit(5)
|
|
89
89
|
```
|
|
90
90
|
|
|
91
|
-
|
|
91
|
+
If you want something very similar to scopes, keep reading to learn about [caching methods](https://github.com/flintinatux/memcacheable#cache-methods).
|
|
92
92
|
|
|
93
93
|
### Cache associations
|
|
94
94
|
|
|
@@ -138,6 +138,31 @@ person.touch # association cache is flushed, but not the fetch_where
|
|
|
138
138
|
person.fetch_kittens # reloads the kittens from the cache, and caches as an association
|
|
139
139
|
```
|
|
140
140
|
|
|
141
|
+
### Cache methods
|
|
142
|
+
|
|
143
|
+
Does your model have a method that eats up lots of calculation time, or perhaps a scope-like method that requires a database query? Cache that bad boy!
|
|
144
|
+
|
|
145
|
+
```ruby
|
|
146
|
+
class Person < ActiveRecord::Base
|
|
147
|
+
has_many :kittens
|
|
148
|
+
|
|
149
|
+
include Memcacheable
|
|
150
|
+
cache_method :random_kitten
|
|
151
|
+
|
|
152
|
+
def random_kitten(seed=Random.new_seed)
|
|
153
|
+
kittens.sample(Random.new seed)
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
**Voila!** Now you get a nice fetch method to cache the results:
|
|
159
|
+
|
|
160
|
+
```ruby
|
|
161
|
+
person.fetch_random_kitten(12345) # => gets your random kitty, and then caches it
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
Notice that the fetch method accepts the same args as the original. **Caveat:** blocks are not accepted, unfortunately. I love blocks, but they don't have a consistent identifier to include in a cache key. So feel free to get creative with args, but not blocks.
|
|
165
|
+
|
|
141
166
|
## Inspiration
|
|
142
167
|
|
|
143
168
|
None of the caching options out there really satisfied my needs, so I wrote this gem. But I was not without inspiration. I learned the basics of Rails caching from the [RailsCasts](http://railscasts.com/) episode on [Model Caching](http://railscasts.com/episodes/115-model-caching-revised), and I borrowed a lot of syntax from the very popular [IdentityCache gem](https://github.com/Shopify/identity_cache) from our friends at [Shopify](http://www.shopify.com/).
|
data/lib/memcacheable.rb
CHANGED
|
@@ -10,6 +10,7 @@ module Memcacheable
|
|
|
10
10
|
autoload :FetchByCriteria
|
|
11
11
|
autoload :FetchHasMany
|
|
12
12
|
autoload :FetchHasOne
|
|
13
|
+
autoload :FetchMethod
|
|
13
14
|
autoload :FetchOne
|
|
14
15
|
autoload :FetchWhere
|
|
15
16
|
autoload :Fetcher
|
|
@@ -52,6 +53,14 @@ module Memcacheable
|
|
|
52
53
|
self.cached_indexes << fields.map(&:to_sym).sort
|
|
53
54
|
end
|
|
54
55
|
|
|
56
|
+
def cache_method(*methods)
|
|
57
|
+
methods.each do |method|
|
|
58
|
+
define_method "fetch_#{method}" do |*args|
|
|
59
|
+
FetchMethod.new(self, method, args).fetch
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
55
64
|
def fetch(id)
|
|
56
65
|
FetchOne.new(self, id).fetch
|
|
57
66
|
end
|
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
module Memcacheable
|
|
2
2
|
class FetchBelongsTo < FetchAssociation
|
|
3
|
+
def fetchable?
|
|
4
|
+
klass.respond_to?(:fetch)
|
|
5
|
+
end
|
|
3
6
|
|
|
4
7
|
def find_on_cache_miss
|
|
5
|
-
klass = association.to_s.camelize.constantize
|
|
6
8
|
id = object.send "#{association}_id"
|
|
7
|
-
|
|
9
|
+
fetchable? ? klass.fetch(id) : object.send(association) rescue nil
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def klass
|
|
13
|
+
@klass ||= association.to_s.camelize.constantize
|
|
8
14
|
end
|
|
9
|
-
|
|
10
15
|
end
|
|
11
16
|
end
|
|
@@ -6,7 +6,7 @@ module Memcacheable
|
|
|
6
6
|
|
|
7
7
|
def find_on_cache_miss
|
|
8
8
|
criteria = { "#{class_name}_id" => object.id }
|
|
9
|
-
fetchable? ? klass.fetch_where(criteria) :
|
|
9
|
+
fetchable? ? klass.fetch_where(criteria) : object.send(association).to_a
|
|
10
10
|
end
|
|
11
11
|
|
|
12
12
|
def klass
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module Memcacheable
|
|
2
|
+
class FetchMethod < Fetcher
|
|
3
|
+
attr_accessor :object, :method, :args
|
|
4
|
+
|
|
5
|
+
def initialize(object, method, args)
|
|
6
|
+
self.object = object
|
|
7
|
+
self.method = method
|
|
8
|
+
self.args = args
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def cache_key
|
|
12
|
+
[object, method, args]
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def description
|
|
16
|
+
"method #{cache_key.to_param}"
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def find_on_cache_miss
|
|
20
|
+
object.send method, *args
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
data/lib/memcacheable/version.rb
CHANGED
|
@@ -20,6 +20,11 @@ class Kitten < FakeModel
|
|
|
20
20
|
include Memcacheable
|
|
21
21
|
cache_index :person_id
|
|
22
22
|
cache_belongs_to :person
|
|
23
|
+
cache_method :meow
|
|
24
|
+
|
|
25
|
+
def meow(how_many=1)
|
|
26
|
+
how_many.times.map{ 'meow' }.join ' '
|
|
27
|
+
end
|
|
23
28
|
end
|
|
24
29
|
|
|
25
30
|
describe Memcacheable do
|
|
@@ -175,6 +180,7 @@ describe Memcacheable do
|
|
|
175
180
|
describe '::cache_has_one' do
|
|
176
181
|
let(:dog) { Dog.new person_id: id }
|
|
177
182
|
before do
|
|
183
|
+
person.stub(:dog).and_return dog
|
|
178
184
|
Dog.stub(:find_by) do |criteria|
|
|
179
185
|
criteria.all?{ |k,v| dog.send(k) == v } ? dog : nil
|
|
180
186
|
end
|
|
@@ -189,7 +195,7 @@ describe Memcacheable do
|
|
|
189
195
|
end
|
|
190
196
|
|
|
191
197
|
it "only queries once and then caches" do
|
|
192
|
-
|
|
198
|
+
person.should_receive(:dog).once
|
|
193
199
|
person.fetch_dog
|
|
194
200
|
person.fetch_dog
|
|
195
201
|
end
|
|
@@ -197,7 +203,7 @@ describe Memcacheable do
|
|
|
197
203
|
it "flushes when touched by association" do
|
|
198
204
|
person.fetch_dog
|
|
199
205
|
person.touch
|
|
200
|
-
|
|
206
|
+
person.should_receive(:dog).once
|
|
201
207
|
person.fetch_dog
|
|
202
208
|
end
|
|
203
209
|
end
|
|
@@ -269,4 +275,29 @@ describe Memcacheable do
|
|
|
269
275
|
person.fetch_kittens
|
|
270
276
|
end
|
|
271
277
|
end
|
|
278
|
+
|
|
279
|
+
describe '::cache_method' do
|
|
280
|
+
let(:kitten) { Kitten.new }
|
|
281
|
+
|
|
282
|
+
it "defines a new fetch method" do
|
|
283
|
+
kitten.should.respond_to?(:fetch_meow)
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
it "calls down to the method correctly on cache miss" do
|
|
287
|
+
kitten.fetch_meow(3) { |sound| sound.upcase }.should eq 'meow meow meow'
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
it "only queries once and then caches" do
|
|
291
|
+
kitten.should_receive(:meow).once
|
|
292
|
+
kitten.fetch_meow
|
|
293
|
+
kitten.fetch_meow
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
it "flushed when touched by an association" do
|
|
297
|
+
kitten.fetch_meow
|
|
298
|
+
kitten.touch
|
|
299
|
+
kitten.should_receive(:meow).once
|
|
300
|
+
kitten.fetch_meow
|
|
301
|
+
end
|
|
302
|
+
end
|
|
272
303
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: memcacheable
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0
|
|
4
|
+
version: 0.1.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Scott McCormack
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2013-
|
|
11
|
+
date: 2013-07-01 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: activerecord
|
|
@@ -116,6 +116,7 @@ files:
|
|
|
116
116
|
- lib/memcacheable/fetch_by_criteria.rb
|
|
117
117
|
- lib/memcacheable/fetch_has_many.rb
|
|
118
118
|
- lib/memcacheable/fetch_has_one.rb
|
|
119
|
+
- lib/memcacheable/fetch_method.rb
|
|
119
120
|
- lib/memcacheable/fetch_one.rb
|
|
120
121
|
- lib/memcacheable/fetch_where.rb
|
|
121
122
|
- lib/memcacheable/fetcher.rb
|