chunky_cache 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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 9550d0ea98aa1a0abf484c0c825ac671b610627781360ca17759d1a4648ea908
4
+ data.tar.gz: e3a09ed7799bc2734400ca4f8c8a4176e656e75d51976a23254574d74a721ba8
5
+ SHA512:
6
+ metadata.gz: 19412f4f00cd70002701925d36b71972cda3505607594b2d8acfa03cb529c74323ea5812bff14606ebf95e6d2e2747912b621c2b36673b2ce5de4717770521ff
7
+ data.tar.gz: 73d976d28947d4f3ad6ef52a38e0c295daebdeb8933ffc529ce0b3b81cdd142778ee9bf263d935597bb13a18dcd40fcf77bfb0f5be1a0e2c40acfdfc9830eea1
data/.gitignore ADDED
@@ -0,0 +1,11 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+
10
+ # rspec failure tracking
11
+ .rspec_status
data/.gitlab-ci.yml ADDED
@@ -0,0 +1,22 @@
1
+ # This file is a template, and might need editing before it works on your project.
2
+ # Official language image. Look for the different tagged releases at:
3
+ # https://hub.docker.com/r/library/ruby/tags/
4
+ image: "ruby:2.5"
5
+
6
+ # Cache gems in between builds
7
+ cache:
8
+ paths:
9
+ - vendor/ruby
10
+
11
+ # This is a basic example for a gem or script which doesn't use
12
+ # services such as redis or postgres
13
+ before_script:
14
+ - ruby -v # Print out ruby version for debugging
15
+ - gem install bundler
16
+ # Uncomment next line if your rails app needs a JS runtime:
17
+ # - apt-get update -q && apt-get install nodejs -yqq
18
+ - bundle install -j $(nproc) --path vendor # Install dependencies into ./vendor/ruby
19
+
20
+ rspec:
21
+ script:
22
+ - bundle exec rspec
data/.rspec ADDED
@@ -0,0 +1,4 @@
1
+ --format documentation
2
+ --order rand
3
+ --color
4
+ --require spec_helper
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in chunky_cache.gemspec
4
+ gemspec
5
+
6
+ gem "rake", "~> 12.0"
7
+ gem "pry"
data/Gemfile.lock ADDED
@@ -0,0 +1,171 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ chunky_cache (0.1.0)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ actioncable (6.1.3)
10
+ actionpack (= 6.1.3)
11
+ activesupport (= 6.1.3)
12
+ nio4r (~> 2.0)
13
+ websocket-driver (>= 0.6.1)
14
+ actionmailbox (6.1.3)
15
+ actionpack (= 6.1.3)
16
+ activejob (= 6.1.3)
17
+ activerecord (= 6.1.3)
18
+ activestorage (= 6.1.3)
19
+ activesupport (= 6.1.3)
20
+ mail (>= 2.7.1)
21
+ actionmailer (6.1.3)
22
+ actionpack (= 6.1.3)
23
+ actionview (= 6.1.3)
24
+ activejob (= 6.1.3)
25
+ activesupport (= 6.1.3)
26
+ mail (~> 2.5, >= 2.5.4)
27
+ rails-dom-testing (~> 2.0)
28
+ actionpack (6.1.3)
29
+ actionview (= 6.1.3)
30
+ activesupport (= 6.1.3)
31
+ rack (~> 2.0, >= 2.0.9)
32
+ rack-test (>= 0.6.3)
33
+ rails-dom-testing (~> 2.0)
34
+ rails-html-sanitizer (~> 1.0, >= 1.2.0)
35
+ actiontext (6.1.3)
36
+ actionpack (= 6.1.3)
37
+ activerecord (= 6.1.3)
38
+ activestorage (= 6.1.3)
39
+ activesupport (= 6.1.3)
40
+ nokogiri (>= 1.8.5)
41
+ actionview (6.1.3)
42
+ activesupport (= 6.1.3)
43
+ builder (~> 3.1)
44
+ erubi (~> 1.4)
45
+ rails-dom-testing (~> 2.0)
46
+ rails-html-sanitizer (~> 1.1, >= 1.2.0)
47
+ activejob (6.1.3)
48
+ activesupport (= 6.1.3)
49
+ globalid (>= 0.3.6)
50
+ activemodel (6.1.3)
51
+ activesupport (= 6.1.3)
52
+ activerecord (6.1.3)
53
+ activemodel (= 6.1.3)
54
+ activesupport (= 6.1.3)
55
+ activestorage (6.1.3)
56
+ actionpack (= 6.1.3)
57
+ activejob (= 6.1.3)
58
+ activerecord (= 6.1.3)
59
+ activesupport (= 6.1.3)
60
+ marcel (~> 0.3.1)
61
+ mimemagic (~> 0.3.2)
62
+ activesupport (6.1.3)
63
+ concurrent-ruby (~> 1.0, >= 1.0.2)
64
+ i18n (>= 1.6, < 2)
65
+ minitest (>= 5.1)
66
+ tzinfo (~> 2.0)
67
+ zeitwerk (~> 2.3)
68
+ builder (3.2.4)
69
+ coderay (1.1.3)
70
+ concurrent-ruby (1.1.8)
71
+ crass (1.0.6)
72
+ diff-lcs (1.4.4)
73
+ erubi (1.10.0)
74
+ globalid (0.4.2)
75
+ activesupport (>= 4.2.0)
76
+ i18n (1.8.9)
77
+ concurrent-ruby (~> 1.0)
78
+ loofah (2.9.0)
79
+ crass (~> 1.0.2)
80
+ nokogiri (>= 1.5.9)
81
+ mail (2.7.1)
82
+ mini_mime (>= 0.1.1)
83
+ marcel (0.3.3)
84
+ mimemagic (~> 0.3.2)
85
+ method_source (1.0.0)
86
+ mimemagic (0.3.5)
87
+ mini_mime (1.0.2)
88
+ mini_portile2 (2.5.0)
89
+ minitest (5.14.4)
90
+ nio4r (2.5.7)
91
+ nokogiri (1.11.1)
92
+ mini_portile2 (~> 2.5.0)
93
+ racc (~> 1.4)
94
+ pry (0.14.0)
95
+ coderay (~> 1.1)
96
+ method_source (~> 1.0)
97
+ racc (1.5.2)
98
+ rack (2.2.3)
99
+ rack-test (1.1.0)
100
+ rack (>= 1.0, < 3)
101
+ rails (6.1.3)
102
+ actioncable (= 6.1.3)
103
+ actionmailbox (= 6.1.3)
104
+ actionmailer (= 6.1.3)
105
+ actionpack (= 6.1.3)
106
+ actiontext (= 6.1.3)
107
+ actionview (= 6.1.3)
108
+ activejob (= 6.1.3)
109
+ activemodel (= 6.1.3)
110
+ activerecord (= 6.1.3)
111
+ activestorage (= 6.1.3)
112
+ activesupport (= 6.1.3)
113
+ bundler (>= 1.15.0)
114
+ railties (= 6.1.3)
115
+ sprockets-rails (>= 2.0.0)
116
+ rails-dom-testing (2.0.3)
117
+ activesupport (>= 4.2.0)
118
+ nokogiri (>= 1.6)
119
+ rails-html-sanitizer (1.3.0)
120
+ loofah (~> 2.3)
121
+ railties (6.1.3)
122
+ actionpack (= 6.1.3)
123
+ activesupport (= 6.1.3)
124
+ method_source
125
+ rake (>= 0.8.7)
126
+ thor (~> 1.0)
127
+ rake (12.3.3)
128
+ rspec-core (3.10.1)
129
+ rspec-support (~> 3.10.0)
130
+ rspec-expectations (3.10.1)
131
+ diff-lcs (>= 1.2.0, < 2.0)
132
+ rspec-support (~> 3.10.0)
133
+ rspec-mocks (3.10.2)
134
+ diff-lcs (>= 1.2.0, < 2.0)
135
+ rspec-support (~> 3.10.0)
136
+ rspec-rails (4.0.2)
137
+ actionpack (>= 4.2)
138
+ activesupport (>= 4.2)
139
+ railties (>= 4.2)
140
+ rspec-core (~> 3.10)
141
+ rspec-expectations (~> 3.10)
142
+ rspec-mocks (~> 3.10)
143
+ rspec-support (~> 3.10)
144
+ rspec-support (3.10.2)
145
+ sprockets (4.0.2)
146
+ concurrent-ruby (~> 1.0)
147
+ rack (> 1, < 3)
148
+ sprockets-rails (3.2.2)
149
+ actionpack (>= 4.0)
150
+ activesupport (>= 4.0)
151
+ sprockets (>= 3.0.0)
152
+ thor (1.1.0)
153
+ tzinfo (2.0.4)
154
+ concurrent-ruby (~> 1.0)
155
+ websocket-driver (0.7.3)
156
+ websocket-extensions (>= 0.1.0)
157
+ websocket-extensions (0.1.5)
158
+ zeitwerk (2.4.2)
159
+
160
+ PLATFORMS
161
+ ruby
162
+
163
+ DEPENDENCIES
164
+ chunky_cache!
165
+ pry
166
+ rails (>= 4)
167
+ rake (~> 12.0)
168
+ rspec-rails
169
+
170
+ BUNDLED WITH
171
+ 2.1.4
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2021 Robert May
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,65 @@
1
+ # chunky_cache
2
+
3
+ This gem does weird things with Rails caching. Well, one weird thing. Have you ever wanted to perform multiple cache calls on a single view, but realised that this gets quite expensive in terms of network calls to your cache? Fret no more!
4
+
5
+ chunky_cache adds two Rails helpers which mess with the rendering order, allowing you to make multiple cache calls _but only execute one actual cache query_. It does this by capturing the view output inside the `chunky_cache` and `cache_chunk` helpers. These are named poorly and confusingly.
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'chunky_cache'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle install
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install chunky_cache
22
+
23
+ ## Usage
24
+
25
+ ```erb
26
+ <%= chunky_cache(expires_in: 10.minutes) do %>
27
+ <h1>Something not cached</h1>
28
+
29
+ <p>
30
+ <%= cache_chunk(:important_message, current_user) %>
31
+ <strong>This is very important, <%= current_user.name %>!</strong>
32
+ <% end %>
33
+
34
+ <%= cache_chunk(:the_actual_message) %>
35
+ <oblique>No, really</oblique>
36
+ <% end %>
37
+ </p>
38
+
39
+ <%= cache_chunk(:footer) %>
40
+ <p>Fin.</p>
41
+ <% end %>
42
+ <% end %>
43
+ ```
44
+
45
+ This will execute only one call to your cache store, using `Rails.cache.fetch_multi`.
46
+
47
+ ## How does it work?
48
+
49
+ 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.
50
+
51
+ `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.
52
+
53
+ ## Development
54
+
55
+ 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.
56
+
57
+ 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).
58
+
59
+ ## Contributing
60
+
61
+ Please feel free to submit bug reports or merge requests. Don't use singlequotes in Ruby or you'll make me mad.
62
+
63
+ ## License
64
+
65
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "chunky_cache"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,29 @@
1
+ require_relative 'lib/chunky_cache/version'
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = "chunky_cache"
5
+ spec.version = ChunkyCache::VERSION
6
+ spec.authors = ["Robert May"]
7
+ spec.email = ["rob@afternoonrobot.co.uk"]
8
+
9
+ spec.summary = %q{Rails cache multi-fetch inside a view}
10
+ spec.description = %q{Multi-fetch optimisation for multiple cached blocks in Rails views.}
11
+ spec.homepage = "https://gitlab.com/robotmay/chunky_cache"
12
+ spec.license = "MIT"
13
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
14
+
15
+ spec.metadata["homepage_uri"] = spec.homepage
16
+ spec.metadata["source_code_uri"] = "https://gitlab.com/robotmay/chunky_cache"
17
+
18
+ # Specify which files should be added to the gem when it is released.
19
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
20
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
21
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
22
+ end
23
+ spec.bindir = "exe"
24
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
25
+ spec.require_paths = ["lib"]
26
+
27
+ spec.add_development_dependency "rails", ["~> 6"]
28
+ spec.add_development_dependency "rspec-rails", ["~> 4"]
29
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails"
4
+ require "chunky_cache/version"
5
+ require "chunky_cache/railtie"
6
+
7
+ module ChunkyCache
8
+ class Error < StandardError; end
9
+ class MissingChunkyCacheError < Error; end
10
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "view_helpers"
4
+
5
+ module ChunkyCache
6
+ class Railtie < ::Rails::Railtie
7
+ initializer "chunky_cache.view_helpers" do |app|
8
+ self.class_eval do
9
+ include ChunkyCache::ViewHelpers
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,3 @@
1
+ module ChunkyCache
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ChunkyCache
4
+ module ViewHelpers
5
+ # Begin an exciting cache block. This has to wrap
6
+ # calls to `cache_chunk`. This will absorb the contents of the block,
7
+ # allowing it to discover the `cache_chunk` calls, before multi-fetching
8
+ # all keys and then reinserting the cached contents or blocks into
9
+ # the correct places in the output.
10
+ #
11
+ # All keyword arguments are passed to the cache store,
12
+ # but Rails only supports `expires_in` for `fetch_multi` anyway.
13
+ #
14
+ # @param expires_in [ActiveSupport::Duration, Integer] expiry time will be passed to the underlying store
15
+ # @return [ActiveSupport::SafeBuffer]
16
+ def chunky_cache(**cache_options)
17
+ @chunky_key_blocks ||= {}
18
+ blocks = @chunky_key_blocks[template_root_key] = {}
19
+
20
+ # Capture the block, storing its output in a string
21
+ big_ol_strang = capture do
22
+ yield
23
+ end
24
+
25
+ # This probably shouldn't happen
26
+ return if big_ol_strang.nil?
27
+
28
+ # Now the cache blocks are populated and the placeholders in place,
29
+ # we multi-fetch all the keys from the cache, or call the `cache_chunk` blocks
30
+ # for missing values.
31
+ chunks = Rails.cache.fetch_multi(*blocks.keys, **cache_options) do |missing_key|
32
+ capture do
33
+ blocks[missing_key].call
34
+ end
35
+ end
36
+
37
+ # Then we replace the placeholders with our new compiled template data
38
+ chunks.each do |key, chunk|
39
+ big_ol_strang.gsub!(key, (chunk || ""))
40
+ end
41
+
42
+ big_ol_strang.html_safe
43
+ end
44
+
45
+ # Denote a cached chunk of markup. This captures the block
46
+ # and instead returns just a placeholder string for replacement
47
+ # at the end of the `chunky_cache` run.
48
+ #
49
+ # @param keys [*Object] one or multiple objects which respond to `#cache_key` or convert to strings
50
+ # @return [String] the placeholder key
51
+ def cache_chunk(*keys, &block)
52
+ raise MissingChunkyCacheError if @chunky_key_blocks.nil?
53
+
54
+ key = keys.map! { |k| k.try(:cache_key) || k.to_s }.unshift(template_root_key).join(":")
55
+
56
+ @chunky_key_blocks[template_root_key][key] = block
57
+
58
+ return key
59
+ end
60
+
61
+ private
62
+
63
+ # Returns the digest of the current template
64
+ #
65
+ # @return [String]
66
+ def template_root_key
67
+ digest_path_from_template(@current_template)
68
+ end
69
+ end
70
+ end
metadata ADDED
@@ -0,0 +1,88 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: chunky_cache
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Robert May
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2021-03-05 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '6'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec-rails
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '4'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '4'
41
+ description: Multi-fetch optimisation for multiple cached blocks in Rails views.
42
+ email:
43
+ - rob@afternoonrobot.co.uk
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - ".gitignore"
49
+ - ".gitlab-ci.yml"
50
+ - ".rspec"
51
+ - Gemfile
52
+ - Gemfile.lock
53
+ - LICENSE.txt
54
+ - README.md
55
+ - Rakefile
56
+ - bin/console
57
+ - bin/setup
58
+ - chunky_cache.gemspec
59
+ - lib/chunky_cache.rb
60
+ - lib/chunky_cache/railtie.rb
61
+ - lib/chunky_cache/version.rb
62
+ - lib/chunky_cache/view_helpers.rb
63
+ homepage: https://gitlab.com/robotmay/chunky_cache
64
+ licenses:
65
+ - MIT
66
+ metadata:
67
+ homepage_uri: https://gitlab.com/robotmay/chunky_cache
68
+ source_code_uri: https://gitlab.com/robotmay/chunky_cache
69
+ post_install_message:
70
+ rdoc_options: []
71
+ require_paths:
72
+ - lib
73
+ required_ruby_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: 2.3.0
78
+ required_rubygems_version: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ requirements: []
84
+ rubygems_version: 3.0.3
85
+ signing_key:
86
+ specification_version: 4
87
+ summary: Rails cache multi-fetch inside a view
88
+ test_files: []