memoized 1.1.1 → 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: 38881d8fc70ecdbf1920e7bbb40d684403d88c4225e53d7a3e426f97ef5f41ac
4
- data.tar.gz: 750f0290f9258b48bcabdf993e0c0a11f9919643b2a944efa5046cdd930d05a8
3
+ metadata.gz: fb2cf278843df2c67e80b301e9eda488f5d1a1fa897601963982f6e39f5780a7
4
+ data.tar.gz: 364c3036a777f8e7492240c23577a12ba154c22e6011a308e19ccd64d77b0f6e
5
5
  SHA512:
6
- metadata.gz: 35dd34457b8c984200f9fe3eefc72539cf6dcf4661d6ade672197a9c0760439fb27d7b577400eb9416db66fb2f69fc8b6302f78f36f6dbb25d79350f5b7ca521
7
- data.tar.gz: 94360c1c038704a77d06258aa76971bdcb875064cbec5a26b090f5764c50eecccddb01c42ecd67b3a15b3c577768a2740160163111900543582ab4677577d994
6
+ metadata.gz: 851942011f26ecaf7b90303d3fbd6a63462b649a7b5311b03417a56f51d83d69b83f722a90d719782aeb21d38e3685c962e14231afe8c98c9223ccb3b998df72
7
+ data.tar.gz: 3e4c2ab30a1ef2d18f4a9afd2f67ba7edc812f136d70364585b9fb1484dbe5211287d058970a5c58ba15adba9d9f7d2a7057d35a4fef6db24cc54b5fe4d8f1d2
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 2.6.7
1
+ 4.0.1
data/CHANGELOG.md CHANGED
@@ -13,6 +13,22 @@ 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
+
24
+ ## 1.1.2 - 2025-01-22
25
+
26
+ ### Compatible changes
27
+
28
+ - Add Ruby 3.4 support
29
+ - Provide dev script `bin/matrix` and adjust REAMDE
30
+ - Move development dependencies out of the gemspec
31
+
16
32
  ## 1.1.1 - 2022-06-22
17
33
 
18
34
  ### Breaking changes
data/Gemfile CHANGED
@@ -1,3 +1,9 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
3
  gemspec
4
+
5
+ gem 'rake', '~> 13.0.6'
6
+ gem 'rspec', '~> 3.12.0'
7
+ gem 'timecop', '~> 0.8.0'
8
+ gem 'prop_check', '~> 1.0.0'
9
+ gem 'gemika'
data/Gemfile.lock CHANGED
@@ -1,30 +1,28 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- memoized (1.1.1)
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
- diff-lcs (1.3)
11
- gemika (0.7.1)
12
- prop_check (0.14.1)
13
- amazing_print (~> 1.2)
14
- rake (10.4.2)
15
- rspec (3.5.0)
16
- rspec-core (~> 3.5.0)
17
- rspec-expectations (~> 3.5.0)
18
- rspec-mocks (~> 3.5.0)
19
- rspec-core (3.5.4)
20
- rspec-support (~> 3.5.0)
21
- rspec-expectations (3.5.0)
9
+ diff-lcs (1.5.0)
10
+ gemika (2.0.0)
11
+ prop_check (1.0.2)
12
+ rake (13.0.6)
13
+ rspec (3.12.0)
14
+ rspec-core (~> 3.12.0)
15
+ rspec-expectations (~> 3.12.0)
16
+ rspec-mocks (~> 3.12.0)
17
+ rspec-core (3.12.0)
18
+ rspec-support (~> 3.12.0)
19
+ rspec-expectations (3.12.2)
22
20
  diff-lcs (>= 1.2.0, < 2.0)
23
- rspec-support (~> 3.5.0)
24
- rspec-mocks (3.5.0)
21
+ rspec-support (~> 3.12.0)
22
+ rspec-mocks (3.12.3)
25
23
  diff-lcs (>= 1.2.0, < 2.0)
26
- rspec-support (~> 3.5.0)
27
- rspec-support (3.5.0)
24
+ rspec-support (~> 3.12.0)
25
+ rspec-support (3.12.0)
28
26
  timecop (0.8.1)
29
27
 
30
28
  PLATFORMS
@@ -33,10 +31,10 @@ PLATFORMS
33
31
  DEPENDENCIES
34
32
  gemika
35
33
  memoized!
36
- prop_check (~> 0.14.1)
37
- rake (~> 10.4.2)
38
- rspec (~> 3.5.0)
34
+ prop_check (~> 1.0.0)
35
+ rake (~> 13.0.6)
36
+ rspec (~> 3.12.0)
39
37
  timecop (~> 0.8.0)
40
38
 
41
39
  BUNDLED WITH
42
- 2.2.21
40
+ 2.3.1
data/README.md CHANGED
@@ -120,20 +120,31 @@ calculate value ...
120
120
 
121
121
  ## Development
122
122
 
123
- There are tests in `spec`. We only accept PRs with tests. To run tests:
123
+ Development
124
+ -----------
124
125
 
125
- - Install Ruby 2.6.1
126
- - Install development dependencies using `bundle install`
127
- - Run tests using `bundle exec rake current_rspec`
126
+ I'm very eager to keep this gem leightweight and on topic. If you're unsure whether a change would make
127
+ it into the gem, [talk to me beforehand](mailto:henning.koch@makandra.de).
128
128
 
129
- We recommend to test large changes against multiple versions of Ruby. Supported combinations are configured in `.github/workflows/test.yml`. We provide some rake tasks to help with this:
129
+ There are tests in `spec`. We only accept PRs with tests. If you create a PR, the tests will automatically run on
130
+ GitHub actions on each push. We will only merge pull requests after a green GitHub actions run.
130
131
 
131
- - Install development dependencies using `bundle exec rake matrix:install`
132
- - Run tests using `bundle exec rake matrix:spec`
132
+ To run tests locally for development you have multiple options:
133
133
 
134
- Note that we have configured GitHub Actions to automatically run tests in all supported Ruby versions and dependency sets after each push. We will only merge pull requests after a green GitHub Actions run.
134
+ 1. Run tests against a specific Ruby version:
135
+ - Install and switch to the Ruby version
136
+ - Install development dependencies using `bundle install`
137
+ - Run tests using `bundle exec rspec`
135
138
 
136
- I'm very eager to keep this gem leightweight and on topic. If you're unsure whether a change would make it into the gem, [talk to me beforehand](mailto:henning.koch@makandra.de).
139
+ 2. Run tests against all Ruby versions:
140
+ - Install all Ruby versions mentioned in `.github/workflows/test.yml`
141
+ - run `dev/matrix` (only supports `rbenv` for switching Ruby versions currently)
142
+
143
+ Hints:
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](github.com/makandra/gemika) README for more detailed development instructions.
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 `dev/matrix` will warn you, if that is not the case. For all other methods you need to ensure that yourself.
137
148
 
138
149
  ## License
139
150
 
@@ -1,3 +1,3 @@
1
1
  module Memoized
2
- VERSION = '1.1.1'
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,16 +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
24
 
25
- s.add_development_dependency('rake', '~> 10.4.2')
26
- s.add_development_dependency('rspec', '~> 3.5.0')
27
- s.add_development_dependency('timecop', '~> 0.8.0')
28
- s.add_development_dependency('prop_check', '~> 0.14.1')
29
- s.add_development_dependency('gemika')
25
+ s.required_ruby_version = '>= 3.0.0'
30
26
  end
metadata CHANGED
@@ -1,93 +1,20 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: memoized
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.1
4
+ version: 1.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Barun Singh
8
8
  - Henning Koch
9
- autorequire:
10
- bindir: bin
9
+ bindir: exe
11
10
  cert_chain: []
12
- date: 2022-06-22 00:00:00.000000000 Z
13
- dependencies:
14
- - !ruby/object:Gem::Dependency
15
- name: rake
16
- requirement: !ruby/object:Gem::Requirement
17
- requirements:
18
- - - "~>"
19
- - !ruby/object:Gem::Version
20
- version: 10.4.2
21
- type: :development
22
- prerelease: false
23
- version_requirements: !ruby/object:Gem::Requirement
24
- requirements:
25
- - - "~>"
26
- - !ruby/object:Gem::Version
27
- version: 10.4.2
28
- - !ruby/object:Gem::Dependency
29
- name: rspec
30
- requirement: !ruby/object:Gem::Requirement
31
- requirements:
32
- - - "~>"
33
- - !ruby/object:Gem::Version
34
- version: 3.5.0
35
- type: :development
36
- prerelease: false
37
- version_requirements: !ruby/object:Gem::Requirement
38
- requirements:
39
- - - "~>"
40
- - !ruby/object:Gem::Version
41
- version: 3.5.0
42
- - !ruby/object:Gem::Dependency
43
- name: timecop
44
- requirement: !ruby/object:Gem::Requirement
45
- requirements:
46
- - - "~>"
47
- - !ruby/object:Gem::Version
48
- version: 0.8.0
49
- type: :development
50
- prerelease: false
51
- version_requirements: !ruby/object:Gem::Requirement
52
- requirements:
53
- - - "~>"
54
- - !ruby/object:Gem::Version
55
- version: 0.8.0
56
- - !ruby/object:Gem::Dependency
57
- name: prop_check
58
- requirement: !ruby/object:Gem::Requirement
59
- requirements:
60
- - - "~>"
61
- - !ruby/object:Gem::Version
62
- version: 0.14.1
63
- type: :development
64
- prerelease: false
65
- version_requirements: !ruby/object:Gem::Requirement
66
- requirements:
67
- - - "~>"
68
- - !ruby/object:Gem::Version
69
- version: 0.14.1
70
- - !ruby/object:Gem::Dependency
71
- name: gemika
72
- requirement: !ruby/object:Gem::Requirement
73
- requirements:
74
- - - ">="
75
- - !ruby/object:Gem::Version
76
- version: '0'
77
- type: :development
78
- prerelease: false
79
- version_requirements: !ruby/object:Gem::Requirement
80
- requirements:
81
- - - ">="
82
- - !ruby/object:Gem::Version
83
- version: '0'
11
+ date: 1980-01-02 00:00:00.000000000 Z
12
+ dependencies: []
84
13
  description: Memoized caches the results of your method calls
85
- email:
86
14
  executables: []
87
15
  extensions: []
88
16
  extra_rdoc_files: []
89
17
  files:
90
- - ".github/workflows/test.yml"
91
18
  - ".gitignore"
92
19
  - ".rspec"
93
20
  - ".ruby-version"
@@ -101,9 +28,6 @@ files:
101
28
  - lib/memoized/parameters.rb
102
29
  - lib/memoized/version.rb
103
30
  - memoized.gemspec
104
- - spec/memoized_spec.rb
105
- - spec/properties_spec.rb
106
- - spec/spec_helper.rb
107
31
  homepage: https://github.com/makandra/memoized
108
32
  licenses:
109
33
  - MIT
@@ -112,7 +36,6 @@ metadata:
112
36
  bug_tracker_uri: https://github.com/makandra/memoized/issues
113
37
  changelog_uri: https://github.com/makandra/memoized/blob/master/CHANGELOG.md
114
38
  rubygems_mfa_required: 'true'
115
- post_install_message:
116
39
  rdoc_options: []
117
40
  require_paths:
118
41
  - lib
@@ -120,15 +43,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
120
43
  requirements:
121
44
  - - ">="
122
45
  - !ruby/object:Gem::Version
123
- version: '0'
46
+ version: 3.0.0
124
47
  required_rubygems_version: !ruby/object:Gem::Requirement
125
48
  requirements:
126
49
  - - ">="
127
50
  - !ruby/object:Gem::Version
128
51
  version: '0'
129
52
  requirements: []
130
- rubygems_version: 3.0.3.1
131
- signing_key:
53
+ rubygems_version: 4.0.3
132
54
  specification_version: 4
133
55
  summary: Memoized caches the results of your method calls
134
56
  test_files: []
@@ -1,38 +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.0.1
24
- gemfile: Gemfile
25
- env:
26
- BUNDLE_GEMFILE: "${{ matrix.gemfile }}"
27
- steps:
28
- - uses: actions/checkout@v2
29
- - name: Install ruby
30
- uses: ruby/setup-ruby@v1
31
- with:
32
- ruby-version: "${{ matrix.ruby }}"
33
- - name: Bundle
34
- run: |
35
- gem install bundler:2.2.21
36
- bundle install --no-deployment
37
- - name: Run tests
38
- run: bundle exec rspec
@@ -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)