chunky_cache 0.1.2 → 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +20 -9
- data/lib/chunky_cache/version.rb +1 -1
- data/lib/chunky_cache/view_helpers.rb +42 -12
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c342e8e301ad9650d1b50e25e74b6b31995b6d0ee649aef74d473c4fe556404d
|
4
|
+
data.tar.gz: 3fb5c2e12003ca7687714366270c4850419784149647254b31a52182ec965727
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dd96272d0a37bfa442df78dddda1227adac58c7c55456b941da1ffbfa919bca70e0fa1131b518f31424cf6a6f9d01333763f1d2815f4cd15c301ff45ec77def3
|
7
|
+
data.tar.gz: '0481cb78d6e06b35f807ec542f41bb823fb62a4a267d09c19a4f3c34a85c22b49c1b7476477964bd90989e182ea3cd0687b0063ff47d62f8817e418c7362bb28'
|
data/README.md
CHANGED
@@ -27,16 +27,16 @@ Or install it yourself as:
|
|
27
27
|
<h1>Something not cached</h1>
|
28
28
|
|
29
29
|
<p>
|
30
|
-
<%= cache_chunk(:important_message, current_user) %>
|
30
|
+
<%= cache_chunk(:important_message, current_user) do %>
|
31
31
|
<strong>This is very important, <%= current_user.name %>!</strong>
|
32
32
|
<% end %>
|
33
33
|
|
34
|
-
<%= cache_chunk(:the_actual_message) %>
|
34
|
+
<%= cache_chunk(:the_actual_message) do %>
|
35
35
|
<oblique>No, really</oblique>
|
36
36
|
<% end %>
|
37
37
|
</p>
|
38
38
|
|
39
|
-
<%= cache_chunk(:footer) %>
|
39
|
+
<%= cache_chunk(:footer) do %>
|
40
40
|
<p>Fin.</p>
|
41
41
|
<% end %>
|
42
42
|
<% end %>
|
@@ -44,7 +44,7 @@ Or install it yourself as:
|
|
44
44
|
|
45
45
|
This will execute only one call to your cache store, using `Rails.cache.fetch_multi`.
|
46
46
|
|
47
|
-
When using `cache_chunk` inside a
|
47
|
+
When using `cache_chunk` inside a loop, use its ability to pass the key components to the block
|
48
48
|
to persist the context (i.e. it'll be super borked if you don't do this):
|
49
49
|
|
50
50
|
```slim
|
@@ -53,17 +53,28 @@ to persist the context (i.e. it'll be super borked if you don't do this):
|
|
53
53
|
h1= article.title
|
54
54
|
```
|
55
55
|
|
56
|
+
`cache_chunk` calls inside partials rendered inside the main `chunky_cache` call will also be picked up, this allows you to execute one network request for multiple chunks inside multiple view renders, e.g.
|
57
|
+
|
58
|
+
```slim
|
59
|
+
= chunky_cache(expires_in: 1.hour) do
|
60
|
+
= render partial: "foxes", collection: @foxes
|
61
|
+
|
62
|
+
# Then inside _foxes.html.slim
|
63
|
+
|
64
|
+
= chunky_cache(expires_in: 1.hour) do # this will defer to the parent call, and isn't necessary
|
65
|
+
= cache_chunk(fox) do |fox|
|
66
|
+
= "Hello #{fox}"
|
67
|
+
```
|
68
|
+
|
56
69
|
## How does it work?
|
57
70
|
|
58
|
-
The helpers use Rails' built-in helper `capture` to consume the contents of their blocks and turn them into strings. `chunky_cache` does this immediately, and returns the final output after mixing everything together. But `cache_chunk`
|
71
|
+
The helpers use Rails' built-in helper `capture` to consume the contents of their blocks and turn them into strings. `chunky_cache` does this immediately, and returns the final output after mixing everything together. But `cache_chunk` doesn't execute its block, instead storing it in an instance variable established by `chunky_cache`, and it then returns a cache key string. At this point the template is thus half-complete, with sections missing and only weird strings in their place.
|
59
72
|
|
60
73
|
`chunky_cache` then performs a cache multi-fetch, passing in all the keys it knows about. For any missing keys, the block captured by `cache_chunk` is executed and returned to the cache. The mix of cached/non-cached chunks are then reinserted into the main block content, replacing the key placeholders. A final compiled string is then returned.
|
61
74
|
|
62
|
-
##
|
63
|
-
|
64
|
-
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
75
|
+
## Why is this useful?
|
65
76
|
|
66
|
-
|
77
|
+
If you run `memcached` as your cache store on the same server as your Rails app, this gem is probably not very useful. Where it shines, however, is when network latency becomes more expensive than what you are caching. It allows you to cache lots of little chunks of markup, with different cache keys, and expend only one network request to fetch it. This allows you to start caching really trivial parts of templates that would never be worth caching normally; like caching individual navigation links in a menu, with active/inactive states, rather than caching the whole menu for each state. You can break up your larger caches into small sections with different keys, allowing parts of a cache to contain user-specific data but sharing generic data for everyone. This can be a useful cache storage size optimisation.
|
67
78
|
|
68
79
|
## Contributing
|
69
80
|
|
data/lib/chunky_cache/version.rb
CHANGED
@@ -14,8 +14,18 @@ module ChunkyCache
|
|
14
14
|
# @param expires_in [ActiveSupport::Duration, Integer] expiry time will be passed to the underlying store
|
15
15
|
# @return [ActiveSupport::SafeBuffer]
|
16
16
|
def chunky_cache(**cache_options)
|
17
|
-
|
18
|
-
|
17
|
+
# Return if the memory cache is already established, as an outer run of
|
18
|
+
# this method is in progress already
|
19
|
+
return capture { yield } if memory_cache.present?
|
20
|
+
|
21
|
+
# Set up the in-memory cache for this block
|
22
|
+
establish_memory_cache(cache_options)
|
23
|
+
|
24
|
+
# Exit out if caching isn't enabled
|
25
|
+
return capture { yield } unless memory_cache[:perform_caching]
|
26
|
+
|
27
|
+
blocks = memory_cache[:key_blocks]
|
28
|
+
output_buffer = ActiveSupport::SafeBuffer.new
|
19
29
|
|
20
30
|
# Capture the block, storing its output in a string
|
21
31
|
big_ol_strang = capture do
|
@@ -24,27 +34,26 @@ module ChunkyCache
|
|
24
34
|
|
25
35
|
# This probably shouldn't happen
|
26
36
|
return if big_ol_strang.nil?
|
27
|
-
|
37
|
+
|
28
38
|
# Now the cache blocks are populated and the placeholders in place,
|
29
39
|
# we multi-fetch all the keys from the cache, or call the `cache_chunk` blocks
|
30
40
|
# for missing values.
|
31
41
|
chunks = Rails.cache.fetch_multi(*blocks.keys, **cache_options) do |missing_key|
|
32
|
-
logger.debug("Chunk cache miss: #{missing_key}")
|
33
|
-
|
34
42
|
capture do
|
35
43
|
block, context = *blocks[missing_key]
|
36
44
|
block.call(*context)
|
37
45
|
end
|
38
46
|
end
|
39
47
|
|
40
|
-
# Then we replace the placeholders with our new compiled template data
|
41
48
|
chunks.each do |key, chunk|
|
42
|
-
|
43
|
-
|
44
|
-
|
49
|
+
pre, big_ol_strang = *big_ol_strang.split(key, 2)
|
50
|
+
output_buffer << pre.html_safe
|
51
|
+
output_buffer << chunk
|
45
52
|
end
|
46
53
|
|
47
|
-
|
54
|
+
reset_memory_cache
|
55
|
+
|
56
|
+
output_buffer
|
48
57
|
end
|
49
58
|
|
50
59
|
# Denote a cached chunk of markup. This captures the block
|
@@ -54,17 +63,38 @@ module ChunkyCache
|
|
54
63
|
# @param context [*Object] one or multiple objects which respond to `#cache_key` or convert to strings
|
55
64
|
# @return [String] the placeholder key
|
56
65
|
def cache_chunk(*context, &block)
|
57
|
-
|
66
|
+
return block.call(*context) if memory_cache.nil? || !memory_cache[:perform_caching]
|
58
67
|
|
59
68
|
key = context.map { |k| k.try(:cache_key) || k.to_s }.unshift(template_root_key).join(":")
|
60
69
|
|
61
|
-
|
70
|
+
memory_cache[:key_blocks][key] = [block, context]
|
62
71
|
|
63
72
|
return key
|
64
73
|
end
|
65
74
|
|
66
75
|
private
|
67
76
|
|
77
|
+
def establish_memory_cache(cache_options, perform_caching: true)
|
78
|
+
if conditional_if = cache_options.delete(:if)
|
79
|
+
perform_caching = (conditional_if.call == true)
|
80
|
+
elsif conditional_unless = cache_options.delete(:unless)
|
81
|
+
perform_caching = (conditional_unless.call == false)
|
82
|
+
end
|
83
|
+
|
84
|
+
@chunky_cache_store = {
|
85
|
+
key_blocks: {},
|
86
|
+
perform_caching: perform_caching
|
87
|
+
}
|
88
|
+
end
|
89
|
+
|
90
|
+
def memory_cache
|
91
|
+
@chunky_cache_store
|
92
|
+
end
|
93
|
+
|
94
|
+
def reset_memory_cache
|
95
|
+
@chunky_cache_store = nil
|
96
|
+
end
|
97
|
+
|
68
98
|
# Returns the digest of the current template
|
69
99
|
#
|
70
100
|
# @return [String]
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: chunky_cache
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Robert May
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-03-
|
11
|
+
date: 2021-03-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -81,7 +81,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
83
|
requirements: []
|
84
|
-
rubygems_version: 3.
|
84
|
+
rubygems_version: 3.1.4
|
85
85
|
signing_key:
|
86
86
|
specification_version: 4
|
87
87
|
summary: Rails cache multi-fetch inside a view
|