mize 0.6.0 → 0.7.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/.all_images.yml +21 -17
- data/.github/workflows/static.yml +51 -0
- data/.rspec +1 -0
- data/CHANGES.md +173 -0
- data/Gemfile +0 -2
- data/LICENSE +19 -0
- data/README.md +144 -29
- data/Rakefile +11 -2
- data/VERSION +1 -1
- data/lib/mize/cache_methods.rb +42 -1
- data/lib/mize/cache_protocol.rb +19 -0
- data/lib/mize/configure.rb +31 -0
- data/lib/mize/default_cache.rb +45 -12
- data/lib/mize/global_clear.rb +15 -1
- data/lib/mize/memoize.rb +65 -9
- data/lib/mize/railtie.rb +7 -0
- data/lib/mize/reload.rb +16 -3
- data/lib/mize/version.rb +7 -2
- data/lib/mize.rb +63 -0
- data/mize.gemspec +12 -10
- data/spec/mize/global_clear_spec.rb +0 -2
- data/spec/mize/memoize_method_spec.rb +0 -2
- data/spec/mize/memoize_reload_spec.rb +0 -2
- data/spec/mize/version_spec.rb +0 -2
- data/spec/mize_spec.rb +13 -0
- data/spec/spec_helper.rb +3 -8
- metadata +31 -18
- data/.tool-versions +0 -1
- data/.utilsrc +0 -26
- data/config/broken_config.yml +0 -1
- data/config/config.yml +0 -13
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: '04349dcaaaec8f657183fc213be81b6c49f182d0687441b7cdd004e561a008a4'
|
|
4
|
+
data.tar.gz: 89f29be0ec81a2d25c4418d818e89afa40e4699529f4d04feccffabb4a0225dc
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6e4ea031b167f232db72a768d892884ea6516b4d1f68603b2e992c95bfed16509838e7df6fc64142944cc5009fff8472a08ede1f88b4767e25e1df9fa2cc980b
|
|
7
|
+
data.tar.gz: a0790fa35f0ac32bd68679670cbdb45efb4173ef1140865ac64f2e891edc8ca49ad6ceb502dedebe87b7897eb64606cbfd7817eebe6f6033f56b693338d27564
|
data/.all_images.yml
CHANGED
|
@@ -1,29 +1,33 @@
|
|
|
1
1
|
dockerfile: |-
|
|
2
|
-
RUN apk add --no-cache build-base git
|
|
3
|
-
RUN bash <<NUR
|
|
4
|
-
if [[ "$(ruby -e 'print RUBY_VERSION')" > '3' ]]
|
|
5
|
-
then
|
|
6
|
-
gem update --system
|
|
7
|
-
gem install gem_hadar bundler
|
|
8
|
-
else
|
|
9
|
-
gem install gem_hadar
|
|
10
|
-
gem install bundler -v 2.4.22
|
|
11
|
-
fi
|
|
12
|
-
NUR
|
|
2
|
+
RUN apk add --no-cache build-base yaml-dev git openssl-dev
|
|
13
3
|
|
|
14
4
|
script: &script |-
|
|
15
5
|
echo -e "\e[1m"
|
|
16
6
|
ruby -v
|
|
17
7
|
echo -e "\e[0m"
|
|
18
|
-
bundle
|
|
19
|
-
rake spec
|
|
8
|
+
bundle install --jobs=$(getconf _NPROCESSORS_ONLN)
|
|
9
|
+
bundle exec rake spec
|
|
20
10
|
|
|
21
|
-
|
|
11
|
+
before: |-
|
|
12
|
+
echo 🏁 Preparing…
|
|
13
|
+
echo Deleting Gemfile.lock
|
|
14
|
+
rm -f Gemfile.lock
|
|
15
|
+
|
|
16
|
+
after: |-
|
|
17
|
+
if [[ "$RESULT" = "1" ]]
|
|
18
|
+
then
|
|
19
|
+
echo 😵 Some tests failed!
|
|
20
|
+
else
|
|
21
|
+
echo 🥳 All tests passed!
|
|
22
|
+
fi
|
|
23
|
+
echo Deleting Gemfile.lock
|
|
24
|
+
rm -f Gemfile.lock
|
|
25
|
+
|
|
26
|
+
fail_fast: true
|
|
22
27
|
|
|
23
28
|
images:
|
|
29
|
+
ruby:4.0-alpine: *script
|
|
30
|
+
ruby:3.4-alpine: *script
|
|
24
31
|
ruby:3.3-alpine: *script
|
|
25
32
|
ruby:3.2-alpine: *script
|
|
26
33
|
ruby:3.1-alpine: *script
|
|
27
|
-
ruby:3.0-alpine: *script
|
|
28
|
-
ruby:2.7-alpine: *script
|
|
29
|
-
ruby:2.6-alpine: *script
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Simple workflow for deploying static content to GitHub Pages
|
|
2
|
+
name: Deploy static content to Pages
|
|
3
|
+
|
|
4
|
+
on:
|
|
5
|
+
# Runs on pushes targeting the default branch
|
|
6
|
+
push:
|
|
7
|
+
branches: [ "master" ]
|
|
8
|
+
|
|
9
|
+
# Allows you to run this workflow manually from the Actions tab
|
|
10
|
+
workflow_dispatch:
|
|
11
|
+
|
|
12
|
+
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
|
|
13
|
+
permissions:
|
|
14
|
+
contents: read
|
|
15
|
+
pages: write
|
|
16
|
+
id-token: write
|
|
17
|
+
|
|
18
|
+
# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
|
|
19
|
+
# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
|
|
20
|
+
concurrency:
|
|
21
|
+
group: "pages"
|
|
22
|
+
cancel-in-progress: false
|
|
23
|
+
|
|
24
|
+
jobs:
|
|
25
|
+
# Single deploy job since we're just deploying
|
|
26
|
+
deploy:
|
|
27
|
+
environment:
|
|
28
|
+
name: github-pages
|
|
29
|
+
url: ${{ steps.deployment.outputs.page_url }}
|
|
30
|
+
runs-on: ubuntu-latest
|
|
31
|
+
steps:
|
|
32
|
+
- name: Checkout
|
|
33
|
+
uses: actions/checkout@v6
|
|
34
|
+
- name: Setup Pages
|
|
35
|
+
uses: actions/configure-pages@v6
|
|
36
|
+
- name: Setup Ruby
|
|
37
|
+
uses: ruby/setup-ruby@v1
|
|
38
|
+
with:
|
|
39
|
+
ruby-version: '4.0'
|
|
40
|
+
- name: Generate Documentation
|
|
41
|
+
run: |
|
|
42
|
+
gem install gem_hadar
|
|
43
|
+
bundle install
|
|
44
|
+
rake doc
|
|
45
|
+
- name: Upload artifact
|
|
46
|
+
uses: actions/upload-pages-artifact@v5
|
|
47
|
+
with:
|
|
48
|
+
path: 'doc'
|
|
49
|
+
- name: Deploy to GitHub Pages
|
|
50
|
+
id: deployment
|
|
51
|
+
uses: actions/deploy-pages@v5
|
data/.rspec
CHANGED
data/CHANGES.md
ADDED
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
# Changes
|
|
2
|
+
|
|
3
|
+
## 2026-10-18 v0.7.0
|
|
4
|
+
|
|
5
|
+
### Breaking
|
|
6
|
+
- Removed support for Ruby **3.0** from the CI test matrix.
|
|
7
|
+
- Removed the vestigial `MonitorMixin` inclusion from `Mize::DefaultCache`, as
|
|
8
|
+
the class is now a plain `Hash` wrapper relying on the GVL for atomicity.
|
|
9
|
+
|
|
10
|
+
### Features
|
|
11
|
+
- Added `Mize.synchronize` API to expose the internal `MUTEX` for atomic
|
|
12
|
+
multi-step operations, with specific handling for `ThreadError` in trap
|
|
13
|
+
contexts.
|
|
14
|
+
- Added a GitHub Actions workflow (`static.yml`) to generate YARD documentation
|
|
15
|
+
and deploy it to GitHub Pages.
|
|
16
|
+
- Added `changelog` configuration to the `Rakefile` to enable automated
|
|
17
|
+
generation of `CHANGES.md`.
|
|
18
|
+
- Added `source_code_uri` metadata to the gemspec.
|
|
19
|
+
|
|
20
|
+
### Improvements
|
|
21
|
+
- Added comprehensive YARD documentation to all library modules (`Mize`,
|
|
22
|
+
`Mize::Memoize`, `Mize::CacheMethods`, `Mize::CacheProtocol`,
|
|
23
|
+
`Mize::Configure`, `Mize::DefaultCache`, `Mize::GlobalClear`,
|
|
24
|
+
`Mize::Railtie`, and `Mize::Reload`).
|
|
25
|
+
- Improved the generated `lib/mize/version.rb` template with module-level and
|
|
26
|
+
constant-level YARD comments.
|
|
27
|
+
- Replaced manual `SimpleCov` initialization in `spec/spec_helper.rb` with
|
|
28
|
+
`gem_hadar/simplecov` and added error handling for missing dependencies.
|
|
29
|
+
- Migrated internal `Mize::MUTEX.synchronize` calls in `global_clear.rb`,
|
|
30
|
+
`memoize.rb`, and `reload.rb` to use the new `Mize.synchronize` API.
|
|
31
|
+
- Removed the obsolete `.utilsrc` configuration file.
|
|
32
|
+
- Removed unused `config/config.yml` and `config/broken_config.yml` files.
|
|
33
|
+
- Corrected the typo "memoziation" to "memoization" in the gem summary and
|
|
34
|
+
description.
|
|
35
|
+
|
|
36
|
+
### Build & CI
|
|
37
|
+
- Updated CI configuration to support Ruby **4.0** by adding `yaml-dev` and
|
|
38
|
+
`openssl-dev` dependencies and updating the bundler setup.
|
|
39
|
+
- Aligned `.all_images.yml` with standard multi-image configuration, including
|
|
40
|
+
`before`/`after` hooks for `Gemfile.lock` cleanup and result echoing.
|
|
41
|
+
- Updated `gem_hadar` development dependency to **2.20.1**.
|
|
42
|
+
- Updated `rubygems_version` in the gemspec to **4.0.22**.
|
|
43
|
+
- Removed `bundle update --all` from the CI script in favor of `bundle install
|
|
44
|
+
--jobs=$(getconf _NPROCESSORS_ONLN)`.
|
|
45
|
+
|
|
46
|
+
### Testing
|
|
47
|
+
- Added `spec/mize_spec.rb` to verify `Mize.synchronize` block return values
|
|
48
|
+
and lock identity.
|
|
49
|
+
- Added `-rspec_helper` to `.rspec` and removed explicit `require
|
|
50
|
+
'spec_helper'` statements from spec files.
|
|
51
|
+
|
|
52
|
+
### Documentation
|
|
53
|
+
- Restructured `README.md` to cover the full API surface, including options
|
|
54
|
+
(`freeze:`, `store_nil:`), keyword arguments, targeted cache clearing, global
|
|
55
|
+
cache, custom cache backends, and Rails integration.
|
|
56
|
+
- Replaced the introductory text with a concise description and added proper
|
|
57
|
+
fenced code blocks with language tags.
|
|
58
|
+
- Removed the redundant "Download" section, folding the repository link into
|
|
59
|
+
the "Repository" section.
|
|
60
|
+
- Added a "Documentation" section to `README.md` linking to the hosted API
|
|
61
|
+
documentation.
|
|
62
|
+
- Updated `README.md` to reflect the removal of `MonitorMixin` from the default
|
|
63
|
+
cache backend description.
|
|
64
|
+
|
|
65
|
+
## 2024-10-17 v0.6.1
|
|
66
|
+
|
|
67
|
+
* Remove deprecated Ruby versions:
|
|
68
|
+
+ Deleted `ruby:2.7-alpine` and `ruby:2.6-alpine` entries
|
|
69
|
+
* Update `.all_images` script:
|
|
70
|
+
+ Added `bundle install` with full index to script
|
|
71
|
+
+ Replaced `rake` with `bundle exec rake spec`
|
|
72
|
+
* Update dependencies and Ruby version:
|
|
73
|
+
+ Update `Gemfile` to use **3.5.18** RubyGems version
|
|
74
|
+
+ Update `Rakefile` to use `debug` development dependency
|
|
75
|
+
+ Update `GemHadar` development dependency to ~> **1.19**
|
|
76
|
+
+ Add `debug` development dependency
|
|
77
|
+
* Add CHANGES.md file
|
|
78
|
+
* Remove `.tool-versions` file
|
|
79
|
+
* Add more method documentation
|
|
80
|
+
* Add license file in written form
|
|
81
|
+
|
|
82
|
+
## 2024-07-25 v0.6.0
|
|
83
|
+
|
|
84
|
+
* **Added support** for keyword arguments in cached methods/functions.
|
|
85
|
+
+ Updated `cached_method` method to accept keyword arguments.
|
|
86
|
+
+ Added test cases for keyword argument handling.
|
|
87
|
+
|
|
88
|
+
## 2024-07-15 v0.5.0
|
|
89
|
+
|
|
90
|
+
* Remove dependency on protocol, add just documentation instead, it's the Ruby
|
|
91
|
+
way.
|
|
92
|
+
* Test on 3.2 and 3.3 rubies as well
|
|
93
|
+
* Modify gem spec's homepage URL from `http://flori.github.com/#{name}` to `https://github.com/flori/#{name}`
|
|
94
|
+
|
|
95
|
+
## 2022-11-21 v0.4.1
|
|
96
|
+
|
|
97
|
+
* Stop supporting Ruby **2.0**
|
|
98
|
+
+ Removed support for Ruby **2.0** in code
|
|
99
|
+
|
|
100
|
+
## 2019-11-15 v0.4.0
|
|
101
|
+
|
|
102
|
+
* **Depend on `protocol` version ~> **2.0**:
|
|
103
|
+
+ Updated dependency to require at least version **2.0** of the `protocol`
|
|
104
|
+
gem.
|
|
105
|
+
|
|
106
|
+
## 2018-02-09 v0.3.5
|
|
107
|
+
|
|
108
|
+
* Significant changes:
|
|
109
|
+
- *Avoid inheriting from `Hash` for default cache*
|
|
110
|
+
+ Replaced `Hash` inheritance with alternative implementation
|
|
111
|
+
|
|
112
|
+
## 2017-11-01 v0.3.4
|
|
113
|
+
|
|
114
|
+
* Added support for quoting names in regular expressions for deletion.
|
|
115
|
+
* Updated the `delete_by_name` method to use quoted names in regexps.
|
|
116
|
+
|
|
117
|
+
## 2017-08-28 v0.3.3
|
|
118
|
+
|
|
119
|
+
* Fixed bug that caused the program to crash when debugging was enabled.
|
|
120
|
+
- Added check for `debugging_enabled?` in method `my_method`.
|
|
121
|
+
```ruby
|
|
122
|
+
def my_method
|
|
123
|
+
return unless @debugging_enabled
|
|
124
|
+
# rest of the method remains unchanged
|
|
125
|
+
end
|
|
126
|
+
```
|
|
127
|
+
- Removed unnecessary code in method `other_method`.
|
|
128
|
+
|
|
129
|
+
## 2017-06-21 v0.3.2
|
|
130
|
+
|
|
131
|
+
* **Avoid problem during rails development**
|
|
132
|
+
+ Added logic to clear wrapped cache when `reload!` is called
|
|
133
|
+
+ Prevents memory waste during Rails development
|
|
134
|
+
|
|
135
|
+
## 2017-06-20 v0.3.1
|
|
136
|
+
|
|
137
|
+
* Protected wrapping during loading phase of classes
|
|
138
|
+
- Prevents threading issues when loading classes in parallel.
|
|
139
|
+
- Added protection for wrapping during the loading phase of classes.
|
|
140
|
+
|
|
141
|
+
## 2017-02-27 v0.3.0
|
|
142
|
+
|
|
143
|
+
* **Store nil results by default**
|
|
144
|
+
+ Added option to disable storing nil results (`store_nil: false`)
|
|
145
|
+
+ Default behavior is to store nil results
|
|
146
|
+
+ Method/Function: `store_nil` (default value: `true`)
|
|
147
|
+
|
|
148
|
+
## 2017-01-23 v0.2.1
|
|
149
|
+
|
|
150
|
+
* *Avoid ruby warning*: Fix a Ruby warning by adding code to avoid it.
|
|
151
|
+
* *Stop tracking objects use ObjectSpace instead*: Replace object tracking with `ObjectSpace` for better performance.
|
|
152
|
+
|
|
153
|
+
## 2016-02-02 v0.2.0
|
|
154
|
+
|
|
155
|
+
* Clear a single method's results from cache:
|
|
156
|
+
- Added `clear_cache` method to the `ResultCache` class.
|
|
157
|
+
- Modified the `calculate_result` method in the `Calculator` class to call
|
|
158
|
+
`clear_cache` before calculating new results.
|
|
159
|
+
|
|
160
|
+
## 2016-02-02 v0.1.0
|
|
161
|
+
|
|
162
|
+
* Added explicit conformance statement.
|
|
163
|
+
* Implemented method to clear a single method's results from cache.
|
|
164
|
+
|
|
165
|
+
## 2016-02-02 v0.0.2
|
|
166
|
+
|
|
167
|
+
* **Use Mize::CacheProtocol** as a marker interface:
|
|
168
|
+
+ Added `Mize::CacheProtocol` class
|
|
169
|
+
+ Updated code to use `Mize::CacheProtocol` as a marker interface
|
|
170
|
+
|
|
171
|
+
## 2016-02-02 v0.0.1
|
|
172
|
+
|
|
173
|
+
* Start
|
data/Gemfile
CHANGED
data/LICENSE
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
Copyright Florian Frank
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
4
|
+
this software and associated documentation files (the “Software”), to deal in
|
|
5
|
+
the Software without restriction, including without limitation the rights to
|
|
6
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
7
|
+
of the Software, and to permit persons to whom the Software is furnished to do
|
|
8
|
+
so, subject to the following conditions:
|
|
9
|
+
|
|
10
|
+
The above copyright notice and this permission notice shall be included in all
|
|
11
|
+
copies or substantial portions of the Software.
|
|
12
|
+
|
|
13
|
+
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
19
|
+
SOFTWARE.
|
data/README.md
CHANGED
|
@@ -1,26 +1,31 @@
|
|
|
1
1
|
# Mize
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Lightweight memoization for Ruby. Annotate any method or function with a
|
|
4
|
+
single `memoize` call and Mize handles result caching, invalidation, and
|
|
5
|
+
Rails-aware reload for you.
|
|
4
6
|
|
|
5
|
-
|
|
7
|
+
Works with Ruby 3.1 – 4.0 (tested via `.all_images.yml`).
|
|
6
8
|
|
|
7
9
|
## Installation
|
|
8
10
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
You can also put this line into your Gemfile
|
|
11
|
+
```sh
|
|
12
|
+
gem install mize
|
|
13
|
+
```
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
or add to your `Gemfile`:
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
```ruby
|
|
18
|
+
gem 'mize'
|
|
19
|
+
```
|
|
18
20
|
|
|
19
21
|
## Usage
|
|
20
22
|
|
|
21
|
-
|
|
23
|
+
### Memoize a method
|
|
22
24
|
|
|
23
|
-
|
|
25
|
+
Results are cached **per receiver**. Two different objects get independent
|
|
26
|
+
caches even for identical arguments:
|
|
27
|
+
|
|
28
|
+
```ruby
|
|
24
29
|
class A
|
|
25
30
|
@@c = 0
|
|
26
31
|
|
|
@@ -32,19 +37,19 @@ end
|
|
|
32
37
|
|
|
33
38
|
a1 = A.new
|
|
34
39
|
a1.foo(23) # => "foo 23 1"
|
|
35
|
-
a1.foo(23) # => "foo 23 1"
|
|
40
|
+
a1.foo(23) # => "foo 23 1" (cached)
|
|
41
|
+
|
|
36
42
|
a2 = A.new
|
|
37
|
-
a2.foo(23) # => "foo 23 2"
|
|
38
|
-
a2.foo(23) # => "foo 23 2"
|
|
39
|
-
a2.mize_cache_clear
|
|
40
|
-
a2.foo(23) # => "foo 23 3"
|
|
41
|
-
a1.foo(23) # => "foo 23 1"
|
|
43
|
+
a2.foo(23) # => "foo 23 2" (different receiver)
|
|
44
|
+
a2.foo(23) # => "foo 23 2" (cached)
|
|
42
45
|
```
|
|
43
46
|
|
|
44
|
-
|
|
45
|
-
this:
|
|
47
|
+
### Memoize a function
|
|
46
48
|
|
|
47
|
-
|
|
49
|
+
Results are cached **globally** — the receiver is ignored. All instances
|
|
50
|
+
share one cache entry per argument set:
|
|
51
|
+
|
|
52
|
+
```ruby
|
|
48
53
|
class B
|
|
49
54
|
@@c = 0
|
|
50
55
|
|
|
@@ -56,18 +61,128 @@ end
|
|
|
56
61
|
|
|
57
62
|
b1 = B.new
|
|
58
63
|
b1.foo(23) # => "foo 23 1"
|
|
59
|
-
b1.foo(23) # => "foo 23 1"
|
|
60
64
|
b2 = B.new
|
|
61
|
-
b2.foo(23) # => "foo 23 1"
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
65
|
+
b2.foo(23) # => "foo 23 1" (same cache as b1)
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Options
|
|
69
|
+
|
|
70
|
+
| Option | Default | Effect |
|
|
71
|
+
|:-------------|:--------|:--------------------------------------|
|
|
72
|
+
| `freeze:` | `false` | Freeze the cached result if possible |
|
|
73
|
+
| `store_nil:` | `true` | Cache `nil` results; `false` recomputes |
|
|
74
|
+
|
|
75
|
+
```ruby
|
|
76
|
+
memoize method:, freeze: true, store_nil: false
|
|
77
|
+
def expensive_query
|
|
78
|
+
# ...
|
|
79
|
+
end
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Keyword arguments are supported and included in the cache key:
|
|
83
|
+
|
|
84
|
+
```ruby
|
|
85
|
+
memoize method:
|
|
86
|
+
def lookup(name, limit: 10)
|
|
87
|
+
# ...
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
lookup("flori") # => computes
|
|
91
|
+
lookup("flori") # => cached
|
|
92
|
+
lookup("flori", limit: 5) # => separate cache entry
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Clearing the cache
|
|
96
|
+
|
|
97
|
+
Clear a single method's cache entries by name:
|
|
98
|
+
|
|
99
|
+
```ruby
|
|
100
|
+
a1.mize_cache_clear_name(:foo)
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Clear **all** cached entries for a receiver (method memoization) or for the
|
|
104
|
+
class (function memoization):
|
|
105
|
+
|
|
106
|
+
```ruby
|
|
107
|
+
a1.mize_cache_clear # method: only a1's cache
|
|
108
|
+
B.mize_cache_clear # function: global shared cache
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Global cache clearing
|
|
112
|
+
|
|
113
|
+
`Mize.cache_clear` walks the entire object space for anything including
|
|
114
|
+
`Mize::CacheProtocol` and clears it. Use this in test setups or teardown:
|
|
115
|
+
|
|
116
|
+
```ruby
|
|
117
|
+
Mize.cache_clear
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Rails integration
|
|
121
|
+
|
|
122
|
+
When Rails is loaded, Mize registers a railtie that calls
|
|
123
|
+
`Mize.cache_clear` on every `to_prepare` block (i.e. on each code reload in
|
|
124
|
+
development). If your model or class defines a `#reload` method, Mize
|
|
125
|
+
prepends its own `reload` that delegates to `super` and then clears
|
|
126
|
+
memoized entries automatically.
|
|
127
|
+
|
|
128
|
+
## Custom cache backend
|
|
129
|
+
|
|
130
|
+
The default backend is a plain in-memory `Hash`. Swap in your own
|
|
131
|
+
(e.g. Redis, Memcached) by implementing the
|
|
132
|
+
`Mize::CacheProtocol` interface:
|
|
133
|
+
|
|
134
|
+
```ruby
|
|
135
|
+
class RedisCache
|
|
136
|
+
include Mize::CacheProtocol
|
|
137
|
+
|
|
138
|
+
def initialize
|
|
139
|
+
@r = Redis.new
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def read(name, options = nil)
|
|
143
|
+
@r.get("mize:#{name}")
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def write(name, value, options = nil)
|
|
147
|
+
@r.set("mize:#{name}", Marshal.dump(value))
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
def exist?(name, options = nil)
|
|
151
|
+
!@r.get("mize:#{name}").nil?
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def delete(name, options = nil)
|
|
155
|
+
@r.del("mize:#{name}")
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def clear(options = nil)
|
|
159
|
+
# delete matching keys or flushdb
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
def each_name(&block)
|
|
163
|
+
# yield each key
|
|
164
|
+
self
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
def prototype
|
|
168
|
+
dup
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
Mize.configure do
|
|
173
|
+
cache RedisCache.new
|
|
174
|
+
end
|
|
66
175
|
```
|
|
67
176
|
|
|
68
|
-
|
|
177
|
+
Any object that `include Mize::CacheProtocol` and implements `read`,
|
|
178
|
+
`write`, `exist?`, `delete`, `clear`, `each_name`, and `prototype` will
|
|
179
|
+
work.
|
|
180
|
+
|
|
181
|
+
## Documentation
|
|
182
|
+
|
|
183
|
+
Complete API documentation is available at: [GitHub.io](https://flori.github.io/mize/)
|
|
69
184
|
|
|
70
|
-
|
|
185
|
+
## Repository
|
|
71
186
|
|
|
72
187
|
* https://github.com/flori/mize
|
|
73
188
|
|
|
@@ -77,4 +192,4 @@ The homepage of this library is located at
|
|
|
77
192
|
|
|
78
193
|
## License
|
|
79
194
|
|
|
80
|
-
|
|
195
|
+
MIT
|
data/Rakefile
CHANGED
|
@@ -7,11 +7,20 @@ GemHadar do
|
|
|
7
7
|
author 'Florian Frank'
|
|
8
8
|
email 'flori@ping.de'
|
|
9
9
|
homepage "https://github.com/flori/#{name}"
|
|
10
|
-
|
|
10
|
+
metadata 'source_code_uri', homepage
|
|
11
|
+
summary 'Library that provides memoization for methods and functions'
|
|
11
12
|
description "#{summary} for Ruby."
|
|
12
13
|
readme 'README.md'
|
|
13
14
|
licenses << 'MIT'
|
|
14
15
|
|
|
16
|
+
changelog do
|
|
17
|
+
filename 'CHANGES.md'
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
github_workflows(
|
|
21
|
+
'static.yml' => { }
|
|
22
|
+
)
|
|
23
|
+
|
|
15
24
|
test_dir 'spec'
|
|
16
25
|
yard_dir 'doc'
|
|
17
26
|
|
|
@@ -19,12 +28,12 @@ GemHadar do
|
|
|
19
28
|
'.AppleDouble', 'tags', '.byebug_history', '.yard*', 'yard', 'doc',
|
|
20
29
|
'errors.lst'
|
|
21
30
|
|
|
22
|
-
|
|
23
31
|
development_dependency 'rake'
|
|
24
32
|
development_dependency 'simplecov'
|
|
25
33
|
development_dependency 'rspec'
|
|
26
34
|
development_dependency 'yard'
|
|
27
35
|
development_dependency 'all_images'
|
|
36
|
+
development_dependency 'debug'
|
|
28
37
|
|
|
29
38
|
required_ruby_version '>= 2'
|
|
30
39
|
end
|
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.
|
|
1
|
+
0.7.0
|
data/lib/mize/cache_methods.rb
CHANGED
|
@@ -1,14 +1,28 @@
|
|
|
1
1
|
require 'mize/cache_protocol'
|
|
2
2
|
require 'mize/default_cache'
|
|
3
3
|
|
|
4
|
+
# Per-object memoization bookkeeping.
|
|
5
|
+
#
|
|
6
|
+
# Mixed into any module that calls +memoize+. Each *object* gets its own
|
|
7
|
+
# lazily-created cache instance (a copy of +Mize.default_cache+), and the
|
|
8
|
+
# key-building helpers below produce stable, argument-sensitive cache keys.
|
|
9
|
+
#
|
|
10
|
+
# State is deliberately kept per-object: two instances of the same memoized
|
|
11
|
+
# class do not share a cache, which is the expected semantics for instance
|
|
12
|
+
# methods.
|
|
4
13
|
module Mize::CacheMethods
|
|
5
14
|
# Clear cached values for all methods/functions of this object.
|
|
15
|
+
#
|
|
16
|
+
# @return [self] The receiver, for chaining.
|
|
6
17
|
def mize_cache_clear
|
|
7
18
|
__mize_cache__.clear
|
|
8
19
|
self
|
|
9
20
|
end
|
|
10
21
|
|
|
11
22
|
# Clear all cached results for the method/function +name+.
|
|
23
|
+
#
|
|
24
|
+
# @param name [String, Symbol] The name of the memoized method/function.
|
|
25
|
+
# @return [self] The receiver, for chaining.
|
|
12
26
|
def mize_cache_clear_name(name)
|
|
13
27
|
name = build_key_prefix(name)
|
|
14
28
|
__mize_cache__.each_name do |n|
|
|
@@ -20,11 +34,19 @@ module Mize::CacheMethods
|
|
|
20
34
|
private
|
|
21
35
|
|
|
22
36
|
# Set the cache object to +cache+.
|
|
37
|
+
#
|
|
38
|
+
# @param cache [Mize::CacheProtocol] The cache backend to store in.
|
|
39
|
+
# @return [Mize::CacheProtocol] The cache backend now stored in +self+.
|
|
23
40
|
def __mize_cache__=(cache)
|
|
24
41
|
@__mize_cache__ = cache
|
|
25
42
|
end
|
|
26
43
|
|
|
27
|
-
# Return the cache object.
|
|
44
|
+
# Return the cache object, creating one on first use.
|
|
45
|
+
#
|
|
46
|
+
# The first access makes a fresh copy of +Mize.default_cache+ (via
|
|
47
|
+
# +prototype+ / "dup") so that each object holds an independent store.
|
|
48
|
+
#
|
|
49
|
+
# @return [Mize::CacheProtocol] This object's cache backend.
|
|
28
50
|
def __mize_cache__
|
|
29
51
|
if defined?(@__mize_cache__)
|
|
30
52
|
@__mize_cache__
|
|
@@ -34,16 +56,35 @@ module Mize::CacheMethods
|
|
|
34
56
|
end
|
|
35
57
|
|
|
36
58
|
# Build a key prefix for +name+.
|
|
59
|
+
#
|
|
60
|
+
# @param name [String, Symbol] The method/function name.
|
|
61
|
+
# @return [String] The namespaced prefix, e.g. +"mize/foo"+.
|
|
37
62
|
def build_key_prefix(name)
|
|
38
63
|
"mize/#{name}"
|
|
39
64
|
end
|
|
40
65
|
|
|
41
66
|
# Build a +name+ prefixed key for the arguments +args+.
|
|
67
|
+
#
|
|
68
|
+
# The argument list is +Marshal#+d so structurally-identical arguments
|
|
69
|
+
# always collide on the same key regardless of object identity.
|
|
70
|
+
#
|
|
71
|
+
# @param name [String, Symbol] The method/function name.
|
|
72
|
+
# @param args [Array] The arguments to key on (positional, then splatted
|
|
73
|
+
# keywords).
|
|
74
|
+
# @return [String] The full cache key.
|
|
42
75
|
def build_key(name, *args)
|
|
43
76
|
"#{build_key_prefix(name)}/#{Marshal.dump(args)}"
|
|
44
77
|
end
|
|
45
78
|
|
|
46
79
|
# Apply the visibility of method +id+ to the wrapper method of this method.
|
|
80
|
+
#
|
|
81
|
+
# The block is expected to (re)define +id+ as +public+; afterwards the
|
|
82
|
+
# original visibility is re-applied in the +ensure+ clause so a memoized
|
|
83
|
+
# +private+ method stays +private+.
|
|
84
|
+
#
|
|
85
|
+
# @param id [String, Symbol] The name of the method whose visibility to
|
|
86
|
+
# mirror.
|
|
87
|
+
# @yield The block that performs the +define_method+ of +id+.
|
|
47
88
|
def memoize_apply_visibility(id)
|
|
48
89
|
visibility = instance_eval do
|
|
49
90
|
case
|
data/lib/mize/cache_protocol.rb
CHANGED
|
@@ -1,2 +1,21 @@
|
|
|
1
|
+
# Marker interface for Mize-compatible cache backends.
|
|
2
|
+
#
|
|
3
|
+
# A cache backend "is a" +Mize::CacheProtocol+ simply by including this
|
|
4
|
+
# module. No methods are mandated — the module exists solely as a type tag
|
|
5
|
+
# that Mize can match against.
|
|
6
|
+
#
|
|
7
|
+
# The primary consumer is +Mize.cache_clear+ (see +Mize::GlobalClear+), which
|
|
8
|
+
# walks the heap with +ObjectSpace.each_object(Mize::CacheProtocol)+ to locate
|
|
9
|
+
# every live cache instance and clear it. This is what turns a per-object
|
|
10
|
+
# cache into a globally clearable one without an explicit registry.
|
|
11
|
+
#
|
|
12
|
+
# @example A minimal compliant backend
|
|
13
|
+
# class MyCache
|
|
14
|
+
# include Mize::CacheProtocol
|
|
15
|
+
#
|
|
16
|
+
# def read(name, options = nil) ... end
|
|
17
|
+
# def write(name, value, options = nil) ... end
|
|
18
|
+
# def clear(options = nil) ... end
|
|
19
|
+
# end
|
|
1
20
|
module Mize::CacheProtocol
|
|
2
21
|
end
|