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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 900e71f999ba2cf5a9996aad4a700b7c22df75e1a240a5fc9e4fc7b2df88e39e
4
- data.tar.gz: 42e100f7f0aef3b9bc932dded4f7d3556bf007ed0057b28932cde7a902025f34
3
+ metadata.gz: c342e8e301ad9650d1b50e25e74b6b31995b6d0ee649aef74d473c4fe556404d
4
+ data.tar.gz: 3fb5c2e12003ca7687714366270c4850419784149647254b31a52182ec965727
5
5
  SHA512:
6
- metadata.gz: cd58b7c0267f3a015a344e68354a83e4b6a74bac7774795d83cfc137331fb7ee750ad7b3732cf66095f8034636fc1959c7d7390ffb840ca5a484cd25cd0b68af
7
- data.tar.gz: 4ce371b52d6d27a4b8aafd1cbaa0edcd2a2620574fa105dda0a7db3e0e9810df6e9dc8f0b27484dc5538648c7e6a2fe624f6f769624a270dd85f4d93b5f00be7
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 block, use its ability to pass the key components to the block
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` instead doesn't execute its block, but stores 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.
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
- ## Development
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
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
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
 
@@ -1,3 +1,3 @@
1
1
  module ChunkyCache
2
- VERSION = "0.1.2"
2
+ VERSION = "0.1.3"
3
3
  end
@@ -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
- @chunky_key_blocks ||= {}
18
- blocks = @chunky_key_blocks[template_root_key] = {}
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
- logger.debug("Chunk key replacement: #{key}")
43
-
44
- big_ol_strang.gsub!(key, (chunk || ""))
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
- big_ol_strang.html_safe
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
- raise MissingChunkyCacheError if @chunky_key_blocks.nil?
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
- @chunky_key_blocks[template_root_key][key] = [block, context]
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.2
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-06 00:00:00.000000000 Z
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.0.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