memoized 1.1.2 → 1.1.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 926d7d513652375d0d0978b5eaff47a4ffacdd0a5f545ea6d3defc9c4a998fef
4
- data.tar.gz: bccf0beaf3128e6ef3a4ac81b0cbebfe0622ebb0371fffe23e5eac92c39a3e05
3
+ metadata.gz: fb2cf278843df2c67e80b301e9eda488f5d1a1fa897601963982f6e39f5780a7
4
+ data.tar.gz: 364c3036a777f8e7492240c23577a12ba154c22e6011a308e19ccd64d77b0f6e
5
5
  SHA512:
6
- metadata.gz: 718c91571de072ec727b30994ea61731a53b9ddaa7bc28cc2ca3cdb44bf7f7de7a1c7421953e859f6a785587831fda4575292e7c87f26cec9fcf3361d8b180e8
7
- data.tar.gz: e9fa3a012d0ccf3a4df5d65e93198bea4f09de92873a3389c8573bda46779ee2cd78cd6b3410c6a424cd552b7f1eb1575aff0d9323caba1f435b3fbc6b923348
6
+ metadata.gz: 851942011f26ecaf7b90303d3fbd6a63462b649a7b5311b03417a56f51d83d69b83f722a90d719782aeb21d38e3685c962e14231afe8c98c9223ccb3b998df72
7
+ data.tar.gz: 3e4c2ab30a1ef2d18f4a9afd2f67ba7edc812f136d70364585b9fb1484dbe5211287d058970a5c58ba15adba9d9f7d2a7057d35a4fef6db24cc54b5fe4d8f1d2
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 3.4.1
1
+ 4.0.1
data/CHANGELOG.md CHANGED
@@ -13,6 +13,14 @@ This project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html
13
13
 
14
14
  -
15
15
 
16
+ ## 1.1.3 - 2026-03-10
17
+
18
+ ### Compatible changes
19
+
20
+ - Add tests for Ruby 4.0
21
+ - Introduce `required_ruby_version` in gemspec so people on legacy Ruby versions don't receive future upgrades
22
+ - Drop tests and support for Ruby < 3
23
+
16
24
  ## 1.1.2 - 2025-01-22
17
25
 
18
26
  ### Compatible changes
data/Gemfile CHANGED
@@ -5,5 +5,5 @@ gemspec
5
5
  gem 'rake', '~> 13.0.6'
6
6
  gem 'rspec', '~> 3.12.0'
7
7
  gem 'timecop', '~> 0.8.0'
8
- gem 'prop_check', '~> 0.18.1'
8
+ gem 'prop_check', '~> 1.0.0'
9
9
  gem 'gemika'
data/Gemfile.lock CHANGED
@@ -1,16 +1,14 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- memoized (1.1.2)
4
+ memoized (1.1.3)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
8
8
  specs:
9
- amazing_print (1.4.0)
10
9
  diff-lcs (1.5.0)
11
- gemika (0.8.2)
12
- prop_check (0.18.1)
13
- amazing_print (~> 1.2)
10
+ gemika (2.0.0)
11
+ prop_check (1.0.2)
14
12
  rake (13.0.6)
15
13
  rspec (3.12.0)
16
14
  rspec-core (~> 3.12.0)
@@ -33,7 +31,7 @@ PLATFORMS
33
31
  DEPENDENCIES
34
32
  gemika
35
33
  memoized!
36
- prop_check (~> 0.18.1)
34
+ prop_check (~> 1.0.0)
37
35
  rake (~> 13.0.6)
38
36
  rspec (~> 3.12.0)
39
37
  timecop (~> 0.8.0)
data/README.md CHANGED
@@ -138,13 +138,13 @@ To run tests locally for development you have multiple options:
138
138
 
139
139
  2. Run tests against all Ruby versions:
140
140
  - Install all Ruby versions mentioned in `.github/workflows/test.yml`
141
- - run `bin/matrix` (only supports `rbenv` for switching Ruby versions currently)
141
+ - run `dev/matrix` (only supports `rbenv` for switching Ruby versions currently)
142
142
 
143
143
  Hints:
144
144
  - At the time of writing this, we only have a single Gemfile. If that isn't the case any longer,
145
- check the gemika README for more detailed development instructions.
145
+ check the [gemika](github.com/makandra/gemika) README for more detailed development instructions.
146
146
  - We recommend to have sufficiently new versions of bundler (> 2.3.0) and rubygems (> 3.3.0) installed for each Ruby version.
147
- - The script `bin/matrix` will warn you, if that is not the case. For all other methods you need to ensure that yourself.
147
+ - The script `dev/matrix` will warn you, if that is not the case. For all other methods you need to ensure that yourself.
148
148
 
149
149
  ## License
150
150
 
@@ -1,3 +1,3 @@
1
1
  module Memoized
2
- VERSION = '1.1.2'
2
+ VERSION = '1.1.3'
3
3
  end
data/memoized.gemspec CHANGED
@@ -8,6 +8,7 @@ Gem::Specification.new do |s|
8
8
  s.homepage = "https://github.com/makandra/memoized"
9
9
  s.summary = "Memoized caches the results of your method calls"
10
10
  s.description = s.summary
11
+ s.license = 'MIT'
11
12
  s.metadata = {
12
13
  'source_code_uri' => s.homepage,
13
14
  'bug_tracker_uri' => 'https://github.com/makandra/memoized/issues',
@@ -15,10 +16,11 @@ Gem::Specification.new do |s|
15
16
  'rubygems_mfa_required' => 'true',
16
17
  }
17
18
 
18
- s.files = `git ls-files`.split("\n").reject { |path| File.lstat(path).symlink? }
19
- s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n").reject { |path| File.lstat(path).symlink? }
20
- s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.files = `git ls-files`.split("\n").select { |f| !File.symlink?(f) && !f.match(%r{^(spec|dev|media|.github)/}) }
21
20
  s.require_paths = ["lib"]
22
21
 
23
- s.license = 'MIT'
22
+ s.bindir = 'exe'
23
+ s.executables = []
24
+
25
+ s.required_ruby_version = '>= 3.0.0'
24
26
  end
metadata CHANGED
@@ -1,22 +1,20 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: memoized
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.2
4
+ version: 1.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Barun Singh
8
8
  - Henning Koch
9
- bindir: bin
9
+ bindir: exe
10
10
  cert_chain: []
11
- date: 2025-01-22 00:00:00.000000000 Z
11
+ date: 1980-01-02 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Memoized caches the results of your method calls
14
- executables:
15
- - matrix
14
+ executables: []
16
15
  extensions: []
17
16
  extra_rdoc_files: []
18
17
  files:
19
- - ".github/workflows/test.yml"
20
18
  - ".gitignore"
21
19
  - ".rspec"
22
20
  - ".ruby-version"
@@ -26,14 +24,10 @@ files:
26
24
  - LICENSE.txt
27
25
  - README.md
28
26
  - Rakefile
29
- - bin/matrix
30
27
  - lib/memoized.rb
31
28
  - lib/memoized/parameters.rb
32
29
  - lib/memoized/version.rb
33
30
  - memoized.gemspec
34
- - spec/memoized_spec.rb
35
- - spec/properties_spec.rb
36
- - spec/spec_helper.rb
37
31
  homepage: https://github.com/makandra/memoized
38
32
  licenses:
39
33
  - MIT
@@ -49,14 +43,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
49
43
  requirements:
50
44
  - - ">="
51
45
  - !ruby/object:Gem::Version
52
- version: '0'
46
+ version: 3.0.0
53
47
  required_rubygems_version: !ruby/object:Gem::Requirement
54
48
  requirements:
55
49
  - - ">="
56
50
  - !ruby/object:Gem::Version
57
51
  version: '0'
58
52
  requirements: []
59
- rubygems_version: 3.6.2
53
+ rubygems_version: 4.0.3
60
54
  specification_version: 4
61
55
  summary: Memoized caches the results of your method calls
62
56
  test_files: []
@@ -1,40 +0,0 @@
1
- ---
2
- name: Tests
3
- 'on':
4
- push:
5
- branches:
6
- - master
7
- pull_request:
8
- branches:
9
- - master
10
- jobs:
11
- test:
12
- runs-on: ubuntu-20.04
13
- strategy:
14
- fail-fast: false
15
- matrix:
16
- include:
17
- - ruby: 2.5.3
18
- gemfile: Gemfile
19
- - ruby: 2.6.7
20
- gemfile: Gemfile
21
- - ruby: 2.7.3
22
- gemfile: Gemfile
23
- - ruby: 3.2.0
24
- gemfile: Gemfile
25
- - ruby: 3.4.1
26
- gemfile: Gemfile
27
- env:
28
- BUNDLE_GEMFILE: "${{ matrix.gemfile }}"
29
- steps:
30
- - uses: actions/checkout@v2
31
- - name: Install ruby
32
- uses: ruby/setup-ruby@v1
33
- with:
34
- ruby-version: "${{ matrix.ruby }}"
35
- - name: Bundle
36
- run: |
37
- gem install bundler:2.3.1
38
- bundle install --no-deployment
39
- - name: Run tests
40
- run: bundle exec rspec
data/bin/matrix DELETED
@@ -1,65 +0,0 @@
1
- #!/bin/bash
2
- set -euo pipefail
3
-
4
- # utility for comparing version strings
5
- # https://stackoverflow.com/questions/4023830/how-to-compare-two-strings-in-dot-separated-version-format-in-bash
6
- function version { echo "$@" | awk -F. '{ printf("%d%03d%03d%03d\n", $1,$2,$3,$4); }'; }
7
-
8
- # store current Ruby version and restore it on exit
9
- original_ruby_version=$(cat .ruby-version)
10
- trap "rbenv local $original_ruby_version" EXIT
11
-
12
- # determine employed Ruby versions (awk command == "strip whitespace", sed command == "delete_prefix")
13
- readarray -t versions < <(grep ruby: .github/workflows/test.yml | awk '{$1=$1};1' | sed 's/- ruby: //' | sort | uniq)
14
- echo "Detected Ruby versions:"
15
- for version in "${versions[@]}"
16
- do
17
- echo "- $version"
18
- done
19
- echo ""
20
-
21
- for version in "${versions[@]}"
22
- do
23
- # switch Ruby version
24
- rbenv local "$version"
25
-
26
- # determine actual versions
27
- ruby_version=$(ruby -v)
28
- rubygems_version=$(gem -v)
29
- bundler_version=$(bundler -v | sed 's/Bundler version //')
30
-
31
- # debug output
32
- echo "====================="
33
- echo "Target Ruby version: $version"
34
- echo ""
35
- echo "Ruby: $ruby_version"
36
- echo "rubygems: $rubygems_version"
37
- echo "Bundler: $bundler_version"
38
- echo "====================="
39
- echo ""
40
-
41
- # version checks (minimum versions to make 'BUNDLED WITH' in Gemfile.lock work correctly)
42
- if [ $(version $rubygems_version) -lt $(version "3.3.0") ]; then
43
- echo "Please ensure that your rubygems version is > 3.3.0 for Ruby $ruby_version!"
44
- echo "Install newest version:"
45
- echo "gem update --system"
46
- echo "Install specific version:"
47
- echo "gem update --system <version>"
48
- exit 1
49
- fi
50
-
51
- if [ $(version $bundler_version) -lt $(version "2.3.0") ]; then
52
- echo "Please ensure that your Bundler version is > 2.3.0 for Ruby $ruby_version!"
53
- echo "Install newest version:"
54
- echo "gem install bundler"
55
- echo "Install specific version:"
56
- echo "gem install bundler:<version>"
57
- exit 1
58
- fi
59
-
60
- # bundle and run specs
61
- rake matrix:install
62
- rake matrix:spec
63
- done
64
-
65
- exit 0
@@ -1,371 +0,0 @@
1
- class MemoizedSpecClass
2
- include Memoized
3
- def no_params() Date.today; end
4
- def with_params?(ndays, an_array) Date.today + ndays + an_array.length; end
5
- def returning_nil!() Date.today; nil; end
6
- def all_param_types(req, opt = 3, *rest, keyreq:, key: 11, **keyrest)
7
- Date.today + (req * opt * rest.inject(&:*) * keyreq * key * keyrest.values.inject(&:*))
8
- end
9
- def only_kwargs(**keyrest)
10
- Date.today + keyrest.values.inject(&:*)
11
- end
12
- memoize :no_params, :with_params?, :returning_nil!, :all_param_types, :only_kwargs
13
- end
14
- class Beepbop < MemoizedSpecClass; end
15
-
16
-
17
- describe Memoized do
18
- let(:today) { Date.today }
19
-
20
- describe '.memoize' do
21
- let(:object) { MemoizedSpecClass.new }
22
- let(:tomorrow) { Date.today + 1 }
23
-
24
- context "for a method with no params" do
25
- it "stores memoized value" do
26
- Timecop.freeze(today)
27
- expect(object.no_params).to eq(today)
28
- Timecop.freeze(tomorrow)
29
- expect(object.no_params).to eq(today)
30
- end
31
- end
32
-
33
- context "for a method with params (and ending in ?)" do
34
- it "stores memoized value" do
35
- Timecop.freeze(today)
36
- expect(object.with_params?(1, [1,2])).to eq(today + 3)
37
- Timecop.freeze(tomorrow)
38
- expect(object.with_params?(1, [1,2])).to eq(today + 3)
39
- end
40
- it "does not confuse one set of inputs for another" do
41
- Timecop.freeze(today)
42
- expect(object.with_params?(1, [1,2])).to eq(today + 3)
43
- expect(object.with_params?(2, [1,2])).to eq(today + 4)
44
- Timecop.freeze(tomorrow)
45
- expect(object.with_params?(1, [1,2])).to eq(today + 3)
46
- expect(object.with_params?(1, [2,2])).to eq(today + 4)
47
- end
48
- end
49
-
50
- context "for a method that returns nil (and ends in !)" do
51
- it "stores the memoized value" do
52
- object.returning_nil!
53
- allow(Date).to receive(:today).and_raise(ArgumentError)
54
- expect(object.returning_nil!).to be_nil
55
- end
56
- end
57
-
58
- context "for a method with all param types" do
59
- it "stores memoized value" do
60
- Timecop.freeze(today)
61
- expect(object.all_param_types(2, 3, 5, 5, keyreq: 7, key: 11, **{ first: 13, second: 13 })).to eq(today + 1951950)
62
- Timecop.freeze(tomorrow)
63
- expect(object.all_param_types(2, 3, 5, 5, keyreq: 7, key: 11, **{ first: 13, second: 13 })).to eq(today + 1951950)
64
- end
65
- it "does not confuse one set of inputs for another" do
66
- Timecop.freeze(today)
67
- expect(object.all_param_types(2, 3, 5, 5, keyreq: 7, key: 11, **{ first: 13, second: 13 })).to eq(today + 1951950)
68
- expect(object.all_param_types(2, 9, 5, keyreq: 7, key: 121, **{ first: 13 })).to eq(today + 990990)
69
- Timecop.freeze(tomorrow)
70
- expect(object.all_param_types(2, 3, 5, 5, keyreq: 7, key: 11, **{ first: 13, second: 13 })).to eq(today + 1951950)
71
- expect(object.all_param_types(2, 9, 5, keyreq: 7, key: 121, **{ first: 13 })).to eq(today + 990990)
72
- end
73
- end
74
-
75
- context "for a method with only keyword rest arguments" do
76
- it "stores memoized value" do
77
- Timecop.freeze(today)
78
- expect(object.only_kwargs(**{ first: 2, second: 3 })).to eq(today + 6)
79
- Timecop.freeze(tomorrow)
80
- expect(object.only_kwargs(**{ first: 2, second: 3 })).to eq(today + 6)
81
- end
82
- it "does not confuse one set of inputs for another" do
83
- Timecop.freeze(today)
84
- expect(object.only_kwargs(**{ first: 2, second: 3 })).to eq(today + 6)
85
- expect(object.only_kwargs(**{ first: 7 })).to eq(today + 7)
86
- Timecop.freeze(tomorrow)
87
- expect(object.only_kwargs(**{ first: 2, second: 3 })).to eq(today + 6)
88
- expect(object.only_kwargs(**{ first: 7 })).to eq(today + 7)
89
- end
90
- end
91
-
92
- context "for subclasses" do
93
- let(:object) { Beepbop.new }
94
- it "still memoizes things" do
95
- Timecop.freeze(today)
96
- expect(object.no_params).to eq(today)
97
- Timecop.freeze(tomorrow)
98
- expect(object.no_params).to eq(today)
99
- end
100
- end
101
-
102
- context 'for private methods' do
103
- class Beirut < MemoizedSpecClass
104
- def foo() bar; end
105
- private
106
- def bar() Date.today; end
107
- memoize :bar
108
- end
109
- let(:object) { Beirut.new }
110
-
111
- it "respects the privacy of the memoized method" do
112
- expect(Beirut.private_method_defined?(:bar)).to be_truthy
113
- expect(Beirut.private_method_defined?(:_unmemoized_bar)).to be_truthy
114
- end
115
-
116
- it "memoizes things" do
117
- Timecop.freeze(today)
118
- expect(object.foo).to eq(today)
119
- Timecop.freeze(today + 1)
120
- expect(object.foo).to eq(today)
121
- end
122
- end
123
-
124
- context 'for protected methods' do
125
- class Wonka < MemoizedSpecClass
126
- def foo() bar; end
127
- protected
128
- def bar() Date.today; end
129
- memoize :bar
130
- end
131
- let(:object) { Wonka.new }
132
-
133
- it "respects the privacy of the memoized method" do
134
- expect(Wonka.protected_method_defined?(:bar)).to be_truthy
135
- expect(Wonka.protected_method_defined?(:_unmemoized_bar)).to be_truthy
136
- end
137
-
138
- it "memoizes things" do
139
- Timecop.freeze(today)
140
- expect(object.foo).to eq(today)
141
- Timecop.freeze(today + 1)
142
- expect(object.foo).to eq(today)
143
- end
144
- end
145
-
146
- context 'for methods with an arity of 0' do
147
- class Arity0 < MemoizedSpecClass
148
- def foo()
149
- end
150
-
151
- memoize :foo
152
- end
153
-
154
- it 'creates a memoized method with an arity of 0' do
155
- expect(Arity0.instance_method(:foo).arity).to eq(0)
156
- end
157
- end
158
-
159
- context 'for methods with an arity of 2' do
160
- class Arity2 < MemoizedSpecClass
161
- def foo(a, b)
162
- end
163
-
164
- memoize :foo
165
- end
166
-
167
- it 'creates a memoized method with an arity of 2' do
168
- expect(Arity2.instance_method(:foo).arity).to eq(2)
169
- end
170
- end
171
-
172
- context 'for methods with splat args' do
173
- class AritySplat < MemoizedSpecClass
174
- def foo(*args)
175
- end
176
-
177
- memoize :foo
178
- end
179
-
180
- it 'creates a memoized method with an arity of -1' do
181
- expect(AritySplat.instance_method(:foo).arity).to eq(-1)
182
- end
183
- end
184
-
185
- context 'for methods with a required and an optional arg' do
186
- class ArityRequiredAndOptional < MemoizedSpecClass
187
- def foo(a, b = 'default')
188
- return [a, b]
189
- end
190
-
191
- memoize :foo
192
- end
193
-
194
- it 'creates a memoized method with a arity of -2' do
195
- expect(ArityRequiredAndOptional.instance_method(:foo).arity).to eq(-2)
196
- end
197
-
198
- it "preserves the optional arg's default value" do
199
- instance = ArityRequiredAndOptional.new
200
- expect(instance.foo('foo')).to eq ['foo', 'default']
201
- end
202
- end
203
-
204
- context 'for methods with a required arg and splat args' do
205
- class ArityArgAndOptional < MemoizedSpecClass
206
- def foo(a, *args)
207
- return [a, args]
208
- end
209
-
210
- memoize :foo
211
- end
212
-
213
- it 'creates a memoized method with a arity of -2' do
214
- expect(ArityArgAndOptional.instance_method(:foo).arity).to eq(-2)
215
- end
216
-
217
- it "passes the splat args to the memoized method" do
218
- instance = ArityArgAndOptional.new
219
- expect(instance.foo('foo', 'bar', 'baz')).to eq ['foo', ['bar', 'baz']]
220
- end
221
- end
222
-
223
- context 'for methods with all types of args' do
224
- class AllArgTypes < MemoizedSpecClass
225
- def foo(required, optional = 3, *rest, req_keyword:, opt_keyword: 11, **keyrest)
226
- return [required, optional, rest, req_keyword, opt_keyword, keyrest]
227
- end
228
-
229
- memoize :foo
230
- end
231
-
232
- it 'the memoized method has the same arity as the original method' do
233
- expect(AllArgTypes.instance_method(:_unmemoized_foo).arity).to eq(-3)
234
- expect(AllArgTypes.instance_method(:foo).arity).to eq(-3)
235
- end
236
-
237
- it 'the memoized method has the same parameters as the original method' do
238
- expect(AllArgTypes.instance_method(:_unmemoized_foo).parameters)
239
- .to eq([
240
- [:req, :required],
241
- [:opt, :optional],
242
- [:rest, :rest],
243
- [:keyreq, :req_keyword],
244
- [:key, :opt_keyword],
245
- [:keyrest, :keyrest]
246
- ])
247
- expect(AllArgTypes.instance_method(:foo).parameters)
248
- .to eq([
249
- [:req, :required],
250
- [:opt, :optional],
251
- [:rest, :rest],
252
- [:keyreq, :req_keyword],
253
- [:key, :opt_keyword],
254
- [:keyrest, :keyrest]
255
- ])
256
- end
257
-
258
- it "passes all args to the original method correctly" do
259
- instance = AllArgTypes.new
260
- expect(instance.foo(2, 333, 5, 5, req_keyword: 7, opt_keyword: 1111, first: 13, second: 17))
261
- .to eq [2, 333, [5, 5], 7, 1111, { first: 13, second: 17 }]
262
- end
263
-
264
- it "preserves the original method's default values" do
265
- instance = AllArgTypes.new
266
- expect(instance.foo(2, req_keyword: 7, third: 19))
267
- .to eq [2, 3, [], 7, 11, { third: 19 }]
268
- end
269
- end
270
-
271
- end
272
-
273
-
274
- describe 'instance methods' do
275
- class MemoizedSpecClass
276
- def today() Date.today; end
277
- def plus_ndays(ndays) Date.today + ndays; end
278
- memoize :today, :plus_ndays
279
- end
280
-
281
- let(:object) { MemoizedSpecClass.new }
282
- before do
283
- Timecop.freeze(today)
284
- expect(object.today).to eq(today)
285
- expect(object.plus_ndays(1)).to eq(today + 1)
286
- expect(object.plus_ndays(3)).to eq(today + 3)
287
- end
288
-
289
- describe '#unmemoize' do
290
- context "for a method with no arguments" do
291
- it "clears the memoized value so it can be rememoized" do
292
- Timecop.freeze(today + 1)
293
- expect(object.today).to eq(today)
294
-
295
- object.unmemoize(:today)
296
- expect(object.today).to eq(today + 1)
297
-
298
- Timecop.freeze(today + 2)
299
- expect(object.today).to eq(today + 1)
300
- end
301
- end
302
-
303
- context "for a method with arguments" do
304
- it "unmemoizes for all inupts" do
305
- Timecop.freeze(today + 1)
306
- expect(object.plus_ndays(1)).to eq(today + 1)
307
- expect(object.plus_ndays(3)).to eq(today + 3)
308
-
309
- object.unmemoize(:plus_ndays)
310
- expect(object.plus_ndays(1)).to eq(today + 2)
311
- expect(object.plus_ndays(3)).to eq(today + 4)
312
-
313
- Timecop.freeze(today + 2)
314
- expect(object.plus_ndays(1)).to eq(today + 2)
315
- expect(object.plus_ndays(3)).to eq(today + 4)
316
- end
317
- end
318
-
319
- it "only affects the method specified" do
320
- Timecop.freeze(today + 1)
321
- expect(object.today).to eq(today)
322
-
323
- object.unmemoize(:plus_ndays)
324
- expect(object.today).to eq(today)
325
-
326
- object.unmemoize(:today)
327
- expect(object.today).to eq(today + 1)
328
- end
329
-
330
- context "for subclasses" do
331
- let(:object) { Beepbop.new }
332
- it "clears the memoized value" do
333
- Timecop.freeze(today + 1)
334
- expect(object.today).to eq(today)
335
-
336
- object.unmemoize(:today)
337
- expect(object.today).to eq(today + 1)
338
-
339
- Timecop.freeze(today + 2)
340
- expect(object.today).to eq(today + 1)
341
- end
342
- end
343
- end
344
-
345
- describe '#unmemoize_all' do
346
- shared_examples_for "unmemoizing methods" do
347
- it "clears all memoized values" do
348
- Timecop.freeze(today + 1)
349
- expect(object.today).to eq(today)
350
- expect(object.plus_ndays(1)).to eq(today + 1)
351
- expect(object.plus_ndays(3)).to eq(today + 3)
352
-
353
- object.unmemoize_all
354
-
355
- expect(object.today).to eq(today + 1)
356
- expect(object.plus_ndays(1)).to eq(today + 2)
357
- expect(object.plus_ndays(3)).to eq(today + 4)
358
- end
359
- end
360
-
361
- it_should_behave_like "unmemoizing methods"
362
-
363
- context "for subclasses" do
364
- let(:object) { Beepbop.new }
365
- it_should_behave_like "unmemoizing methods"
366
- end
367
- end
368
-
369
- end
370
-
371
- end
@@ -1,222 +0,0 @@
1
- unless RUBY_VERSION == '2.5.3'
2
- describe "#memoize" do
3
- include PropCheck
4
- include PropCheck::Generators
5
- include Memoized
6
-
7
- before do
8
- PropCheck::Property.configure do |config|
9
- # CAUTION:
10
- # 100 (default) takes 8 seconds
11
- # 300 takes 11 minutes
12
- config.n_runs = 100
13
- end
14
- end
15
-
16
- it "does not change the method's arity" do
17
- forall(
18
- array(
19
- tuple(
20
- one_of(
21
- constant(:req), constant(:opt), constant(:rest), constant(:keyreq), constant(:key), constant(:keyrest)
22
- ),
23
- simple_symbol.map do |sym|
24
- "param_#{sym}".to_sym
25
- end
26
- )
27
- )
28
- ) do |parameters|
29
- # params now have proper names (no :"", no Ruby keywords) due to the .map in the generator above
30
- unique_names = parameters.uniq { |v| v[1] }
31
- single_args_and_kwargs = unique_names.uniq do |v|
32
- if [:rest, :keyrest].include?(v[0])
33
- v[0]
34
- else
35
- v[1]
36
- end
37
- end
38
-
39
- mp = Memoized::Parameters.new(single_args_and_kwargs)
40
- puts mp.debug_info if ENV['DEBUG'] == 'true'
41
-
42
- eval(<<-RUBY)
43
- class MemoizedPropertyClass
44
- include Memoized
45
-
46
- def parameter_dummy(#{mp.signature})
47
- 42
48
- end
49
-
50
- @old_arity = new.method(:parameter_dummy).arity
51
- memoize :parameter_dummy
52
- @new_arity = new.method(:parameter_dummy).arity
53
-
54
- # cleanup to get rid of warnings
55
- remove_method :_unmemoized_parameter_dummy
56
- remove_method :parameter_dummy
57
- end
58
- RUBY
59
-
60
- expect(MemoizedPropertyClass.instance_variable_get(:@new_arity))
61
- .to eq(MemoizedPropertyClass.instance_variable_get(:@old_arity))
62
- end
63
- end
64
-
65
- it "does not change the method's parameters" do
66
- forall(
67
- array(
68
- tuple(
69
- one_of(
70
- constant(:req), constant(:opt), constant(:rest), constant(:keyreq), constant(:key), constant(:keyrest)
71
- ),
72
- simple_symbol.map do |sym|
73
- "param_#{sym}".to_sym
74
- end
75
- )
76
- )
77
- ) do |parameters|
78
- # params now have proper names (no :"", no Ruby keywords) due to the .map in the generator above
79
- unique_names = parameters.uniq { |v| v[1] }
80
- single_args_and_kwargs = unique_names.uniq do |v|
81
- if [:rest, :keyrest].include?(v[0])
82
- v[0]
83
- else
84
- v[1]
85
- end
86
- end
87
-
88
- mp = Memoized::Parameters.new(single_args_and_kwargs)
89
- puts mp.debug_info if ENV['DEBUG'] == 'true'
90
-
91
- eval(<<-RUBY)
92
- class MemoizedPropertyClass
93
- include Memoized
94
-
95
- def parameter_dummy(#{mp.signature})
96
- 42
97
- end
98
-
99
- @old_parameters = new.method(:parameter_dummy).parameters
100
- memoize :parameter_dummy
101
- @new_parameters = new.method(:parameter_dummy).parameters
102
-
103
- # cleanup to get rid of warnings
104
- remove_method :_unmemoized_parameter_dummy
105
- remove_method :parameter_dummy
106
- end
107
- RUBY
108
-
109
- expect(MemoizedPropertyClass.instance_variable_get(:@new_parameters))
110
- .to eq(MemoizedPropertyClass.instance_variable_get(:@old_parameters))
111
- end
112
- end
113
-
114
- it "does not change the method's value" do
115
- forall(
116
- array(
117
- tuple(
118
- one_of(
119
- constant(:req), constant(:opt), constant(:rest), constant(:keyreq), constant(:key), constant(:keyrest)
120
- ),
121
- simple_symbol.map do |sym|
122
- "param_#{sym}".to_sym
123
- end
124
- )
125
- )
126
- ) do |parameters|
127
- # params now have proper names (no :"", no Ruby keywords) due to the .map in the generator above
128
- unique_names = parameters.uniq { |v| v[1] }
129
- single_args_and_kwargs = unique_names.uniq do |v|
130
- if [:rest, :keyrest].include?(v[0])
131
- v[0]
132
- else
133
- v[1]
134
- end
135
- end
136
-
137
- mp = Memoized::Parameters.new(single_args_and_kwargs)
138
- puts mp.debug_info if ENV['DEBUG'] == 'true'
139
-
140
- eval(<<-RUBY)
141
- class MemoizedPropertyClass
142
- include Memoized
143
-
144
- def parameter_dummy(#{mp.signature})
145
- #{mp.test_body}
146
- end
147
-
148
- @old_value = new.parameter_dummy(#{mp.test_arguments})
149
- memoize :parameter_dummy
150
- @new_value = new.parameter_dummy(#{mp.test_arguments})
151
-
152
- # cleanup to get rid of warnings
153
- remove_method :_unmemoized_parameter_dummy
154
- remove_method :parameter_dummy
155
- end
156
- RUBY
157
-
158
- expect(MemoizedPropertyClass.instance_variable_get(:@new_value))
159
- .to eq(MemoizedPropertyClass.instance_variable_get(:@old_value))
160
- end
161
- end
162
-
163
- it "computes the correct value" do
164
- forall(array(choose(15), min: 6, max: 6)) do |parameter_multiplicities|
165
-
166
- params = []
167
-
168
- parameter_multiplicities[0].times.with_index do |counter|
169
- params << [:req, "required_#{counter}".to_sym]
170
- end
171
-
172
- parameter_multiplicities[1].times.with_index do |counter|
173
- params << [:opt, "optional_#{counter}".to_sym]
174
- end
175
-
176
- if parameter_multiplicities[2] != 0
177
- params << [:rest, :args]
178
- end
179
-
180
- parameter_multiplicities[3].times.with_index do |counter|
181
- params << [:keyreq, "required_kw_#{counter}".to_sym]
182
- end
183
-
184
- parameter_multiplicities[4].times.with_index do |counter|
185
- params << [:key, "optional_kw_#{counter}".to_sym]
186
- end
187
-
188
- if parameter_multiplicities[5] != 0
189
- params << [:keyrest, :kwargs]
190
- end
191
-
192
- mp = Memoized::Parameters.new(params, parameter_multiplicities[2], parameter_multiplicities[5])
193
-
194
- puts mp.debug_info if ENV['DEBUG'] == 'true'
195
-
196
- eval(<<-RUBY)
197
- class MemoizedPropertyClass
198
- include Memoized
199
-
200
- def parameter_dummy(#{mp.signature})
201
- #{mp.test_body}
202
- end
203
-
204
- memoize :parameter_dummy
205
- @value = new.parameter_dummy(#{mp.test_arguments})
206
-
207
- # cleanup to get rid of warnings
208
- remove_method :_unmemoized_parameter_dummy
209
- remove_method :parameter_dummy
210
- end
211
- RUBY
212
-
213
- expected_result = [2, 3, 5, 7, 11, 13].zip(parameter_multiplicities).map do |base, exponent|
214
- base ** exponent
215
- end.inject(&:*)
216
-
217
- expect(MemoizedPropertyClass.instance_variable_get(:@value))
218
- .to eq(expected_result)
219
- end
220
- end
221
- end
222
- end
data/spec/spec_helper.rb DELETED
@@ -1,88 +0,0 @@
1
- require 'date'
2
- require 'timecop'
3
- require 'memoized'
4
- if Gem::Version.new(RUBY_VERSION) > Gem::Version.new('2.5.3')
5
- require 'prop_check'
6
- end
7
-
8
- RSpec.configure do |config|
9
- config.warnings = true
10
- config.order = :random
11
- Kernel.srand config.seed
12
- end
13
-
14
- module Memoized
15
- class Parameters
16
- attr_accessor :args_count, :kwargs_count
17
-
18
- def test_body
19
- params.map(&Parameters.method(:to_test_body)).join(" * ")
20
- end
21
-
22
- def self.to_test_body((param_type, param_name))
23
- case param_type
24
- when :req
25
- "#{param_name}"
26
- when :opt
27
- "#{param_name}"
28
- when :rest
29
- "#{param_name}.inject(&:*)"
30
- when :keyreq
31
- "#{param_name}"
32
- when :key
33
- "#{param_name}"
34
- when :keyrest
35
- "#{param_name}.values.inject(&:*)"
36
- else raise "unknown parameter type"
37
- end
38
- end
39
-
40
- def test_arguments
41
- params.map(&Parameters.new([], @args_count, @kwargs_count).method(:to_test_arguments)).join(", ")
42
- end
43
-
44
- def to_test_arguments((param_type, param_name))
45
- case param_type
46
- when :req
47
- "2"
48
- when :opt
49
- "3"
50
- when :rest
51
- if @args_count.nil?
52
- "5, 5, 5"
53
- else
54
- (["5"] * @args_count).join(', ')
55
- end
56
- when :keyreq
57
- "#{param_name}: 7"
58
- when :key
59
- "#{param_name}: 11"
60
- when :keyrest
61
- if @kwargs_count.nil?
62
- "**{ first: 13, second: 13 }"
63
- else
64
- kwargs_list = (1..@kwargs_count).map.with_index do |counter|
65
- "kwarg_#{counter}: 13"
66
- end
67
- "**{ #{kwargs_list.join(', ')} }"
68
- end
69
- else raise "unknown parameter type"
70
- end
71
- end
72
-
73
- def debug_info
74
- "#{@req_params.size} - #{@opt_params.size} - #{@args_count || @rest_params.size} " \
75
- "| #{@keyreq_params.size} - #{@key_params.size} - #{@kwargs_count || @keyrest_params.size}"
76
- end
77
- end
78
- end
79
-
80
- module ParametersTestExtension
81
- def initialize(parameters = [], args_count = nil, kwargs_count = nil)
82
- super(parameters)
83
- @args_count = args_count
84
- @kwargs_count = kwargs_count
85
- end
86
- end
87
-
88
- Memoized::Parameters.prepend(ParametersTestExtension)