chunky_cache 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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: []