memo_wise 1.0.0 → 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/PULL_REQUEST_TEMPLATE.md +2 -2
- data/.github/workflows/main.yml +1 -1
- data/.gitignore +1 -0
- data/.rubocop.yml +16 -1
- data/CHANGELOG.md +55 -2
- data/Gemfile.lock +30 -30
- data/README.md +74 -19
- data/benchmarks/Gemfile +4 -2
- data/benchmarks/benchmarks.rb +149 -132
- data/lib/memo_wise/internal_api.rb +183 -155
- data/lib/memo_wise/version.rb +1 -1
- data/lib/memo_wise.rb +241 -114
- data/memo_wise.gemspec +1 -0
- metadata +3 -4
- data/benchmarks/.ruby-version +0 -1
- data/benchmarks/Gemfile.lock +0 -29
data/lib/memo_wise.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "set"
|
4
|
+
|
3
5
|
require "memo_wise/internal_api"
|
4
6
|
require "memo_wise/version"
|
5
7
|
|
@@ -23,7 +25,7 @@ require "memo_wise/version"
|
|
23
25
|
# - {.memo_wise} for API and usage examples.
|
24
26
|
# - {file:README.md} for general project information.
|
25
27
|
#
|
26
|
-
module MemoWise
|
28
|
+
module MemoWise
|
27
29
|
# Constructor to set up memoization state before
|
28
30
|
# [calling the original](https://medium.com/@jeremy_96642/ruby-method-auditing-using-module-prepend-4f4e69aacd95)
|
29
31
|
# constructor.
|
@@ -54,7 +56,7 @@ module MemoWise # rubocop:disable Metrics/ModuleLength
|
|
54
56
|
# :nocov:
|
55
57
|
all_args = RUBY_VERSION < "2.7" ? "*" : "..."
|
56
58
|
# :nocov:
|
57
|
-
class_eval
|
59
|
+
class_eval <<~HEREDOC, __FILE__, __LINE__ + 1
|
58
60
|
# On Ruby 2.7 or greater:
|
59
61
|
#
|
60
62
|
# def initialize(...)
|
@@ -73,7 +75,7 @@ module MemoWise # rubocop:disable Metrics/ModuleLength
|
|
73
75
|
MemoWise::InternalAPI.create_memo_wise_state!(self)
|
74
76
|
super
|
75
77
|
end
|
76
|
-
|
78
|
+
HEREDOC
|
77
79
|
|
78
80
|
# @private
|
79
81
|
#
|
@@ -89,7 +91,7 @@ module MemoWise # rubocop:disable Metrics/ModuleLength
|
|
89
91
|
# prepend MemoWise
|
90
92
|
# end
|
91
93
|
#
|
92
|
-
def self.prepended(target)
|
94
|
+
def self.prepended(target)
|
93
95
|
class << target
|
94
96
|
# Allocator to set up memoization state before
|
95
97
|
# [calling the original](https://medium.com/@jeremy_96642/ruby-method-auditing-using-module-prepend-4f4e69aacd95)
|
@@ -109,7 +111,7 @@ module MemoWise # rubocop:disable Metrics/ModuleLength
|
|
109
111
|
end
|
110
112
|
|
111
113
|
# NOTE: See YARD docs for {.memo_wise} directly below this method!
|
112
|
-
def memo_wise(method_name_or_hash)
|
114
|
+
def memo_wise(method_name_or_hash)
|
113
115
|
klass = self
|
114
116
|
case method_name_or_hash
|
115
117
|
when Symbol
|
@@ -120,6 +122,23 @@ module MemoWise # rubocop:disable Metrics/ModuleLength
|
|
120
122
|
MemoWise::InternalAPI.original_class_from_singleton(klass)
|
121
123
|
)
|
122
124
|
end
|
125
|
+
|
126
|
+
# Ensures a module extended by another class/module still works
|
127
|
+
# e.g. rails `ClassMethods` module
|
128
|
+
if klass.is_a?(Module) && !klass.is_a?(Class)
|
129
|
+
# Using `extended` without `included` & `prepended`
|
130
|
+
# As a call to `create_memo_wise_state!` is already included in
|
131
|
+
# `.allocate`/`#initialize`
|
132
|
+
#
|
133
|
+
# But a module/class extending another module with memo_wise
|
134
|
+
# would not call `.allocate`/`#initialize` before calling methods
|
135
|
+
#
|
136
|
+
# On method call `@_memo_wise` would still be `nil`
|
137
|
+
# causing error when fetching cache from `@_memo_wise`
|
138
|
+
def klass.extended(base)
|
139
|
+
MemoWise::InternalAPI.create_memo_wise_state!(base)
|
140
|
+
end
|
141
|
+
end
|
123
142
|
when Hash
|
124
143
|
unless method_name_or_hash.keys == [:self]
|
125
144
|
raise ArgumentError,
|
@@ -137,92 +156,159 @@ module MemoWise # rubocop:disable Metrics/ModuleLength
|
|
137
156
|
klass = klass.singleton_class
|
138
157
|
end
|
139
158
|
|
140
|
-
|
141
|
-
|
159
|
+
if klass.singleton_class?
|
160
|
+
# This ensures that a memoized method defined on a parent class can
|
161
|
+
# still be used in a child class.
|
162
|
+
klass.module_eval <<~HEREDOC, __FILE__, __LINE__ + 1
|
163
|
+
def inherited(subclass)
|
164
|
+
super
|
165
|
+
MemoWise::InternalAPI.create_memo_wise_state!(subclass)
|
166
|
+
end
|
167
|
+
HEREDOC
|
142
168
|
end
|
143
169
|
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
170
|
+
raise ArgumentError, "#{method_name.inspect} must be a Symbol" unless method_name.is_a?(Symbol)
|
171
|
+
|
172
|
+
visibility = MemoWise::InternalAPI.method_visibility(klass, method_name)
|
173
|
+
original_memo_wised_name = MemoWise::InternalAPI.original_memo_wised_name(method_name)
|
148
174
|
method = klass.instance_method(method_name)
|
149
175
|
|
150
176
|
klass.send(:alias_method, original_memo_wised_name, method_name)
|
151
177
|
klass.send(:private, original_memo_wised_name)
|
152
178
|
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
179
|
+
method_arguments = MemoWise::InternalAPI.method_arguments(method)
|
180
|
+
|
181
|
+
case method_arguments
|
182
|
+
when MemoWise::InternalAPI::NONE
|
183
|
+
# Zero-arg methods can use simpler/more performant logic because the
|
184
|
+
# hash key is just the method name.
|
185
|
+
klass.send(:define_method, method_name) do # Ruby 2.4's `define_method` is private in some cases
|
186
|
+
index = MemoWise::InternalAPI.index(self, method_name)
|
187
|
+
klass.module_eval <<~HEREDOC, __FILE__, __LINE__ + 1
|
188
|
+
def #{method_name}
|
189
|
+
if @_memo_wise_sentinels[#{index}]
|
190
|
+
@_memo_wise[#{index}]
|
191
|
+
else
|
192
|
+
ret = @_memo_wise[#{index}] = #{original_memo_wised_name}
|
193
|
+
@_memo_wise_sentinels[#{index}] = true
|
194
|
+
ret
|
195
|
+
end
|
166
196
|
end
|
197
|
+
HEREDOC
|
198
|
+
|
199
|
+
klass.send(visibility, method_name)
|
200
|
+
send(method_name)
|
201
|
+
end
|
202
|
+
when MemoWise::InternalAPI::ONE_REQUIRED_POSITIONAL, MemoWise::InternalAPI::ONE_REQUIRED_KEYWORD
|
203
|
+
key = method.parameters.first.last
|
204
|
+
# NOTE: Ruby 2.6 and below, and TruffleRuby 3.0, break when we use
|
205
|
+
# `define_method(...) do |*args, **kwargs|`. Instead we must use the
|
206
|
+
# simpler `|*args|` pattern. We can't just do this always though
|
207
|
+
# because Ruby 2.7 and above require `|*args, **kwargs|` to work
|
208
|
+
# correctly.
|
209
|
+
# See: https://blog.saeloun.com/2019/10/07/ruby-2-7-keyword-arguments-redesign.html#ruby-26
|
210
|
+
# :nocov:
|
211
|
+
if RUBY_VERSION < "2.7" || RUBY_ENGINE == "truffleruby"
|
212
|
+
klass.send(:define_method, method_name) do |*args| # Ruby 2.4's `define_method` is private in some cases
|
213
|
+
index = MemoWise::InternalAPI.index(self, method_name)
|
214
|
+
klass.module_eval <<~HEREDOC, __FILE__, __LINE__ + 1
|
215
|
+
def #{method_name}(#{MemoWise::InternalAPI.args_str(method)})
|
216
|
+
_memo_wise_hash = (@_memo_wise[#{index}] ||= {})
|
217
|
+
_memo_wise_output = _memo_wise_hash[#{key}]
|
218
|
+
if _memo_wise_output || _memo_wise_hash.key?(#{key})
|
219
|
+
_memo_wise_output
|
220
|
+
else
|
221
|
+
_memo_wise_hash[#{key}] = #{original_memo_wised_name}(#{MemoWise::InternalAPI.call_str(method)})
|
222
|
+
end
|
223
|
+
end
|
224
|
+
HEREDOC
|
225
|
+
|
226
|
+
klass.send(visibility, method_name)
|
227
|
+
send(method_name, *args)
|
167
228
|
end
|
168
|
-
|
169
|
-
else
|
170
|
-
if MemoWise::InternalAPI.has_only_required_args?(method)
|
171
|
-
args_str = method.parameters.map do |type, name|
|
172
|
-
"#{name}#{':' if type == :keyreq}"
|
173
|
-
end.join(", ")
|
174
|
-
args_str = "(#{args_str})"
|
175
|
-
call_str = method.parameters.map do |type, name|
|
176
|
-
type == :req ? name : "#{name}: #{name}"
|
177
|
-
end.join(", ")
|
178
|
-
call_str = "(#{call_str})"
|
179
|
-
fetch_key = method.parameters.map(&:last)
|
180
|
-
fetch_key = if fetch_key.size > 1
|
181
|
-
"[#{fetch_key.join(', ')}].freeze"
|
182
|
-
else
|
183
|
-
fetch_key.first.to_s
|
184
|
-
end
|
229
|
+
# :nocov:
|
185
230
|
else
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
231
|
+
klass.define_method(method_name) do |*args, **kwargs|
|
232
|
+
index = MemoWise::InternalAPI.index(self, method_name)
|
233
|
+
klass.module_eval <<~HEREDOC, __FILE__, __LINE__ + 1
|
234
|
+
def #{method_name}(#{MemoWise::InternalAPI.args_str(method)})
|
235
|
+
_memo_wise_hash = (@_memo_wise[#{index}] ||= {})
|
236
|
+
_memo_wise_output = _memo_wise_hash[#{key}]
|
237
|
+
if _memo_wise_output || _memo_wise_hash.key?(#{key})
|
238
|
+
_memo_wise_output
|
239
|
+
else
|
240
|
+
_memo_wise_hash[#{key}] = #{original_memo_wised_name}(#{MemoWise::InternalAPI.call_str(method)})
|
241
|
+
end
|
242
|
+
end
|
243
|
+
HEREDOC
|
244
|
+
|
245
|
+
klass.send(visibility, method_name)
|
246
|
+
send(method_name, *args, **kwargs)
|
202
247
|
end
|
203
248
|
end
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
249
|
+
# MemoWise::InternalAPI::MULTIPLE_REQUIRED, MemoWise::InternalAPI::SPLAT,
|
250
|
+
# MemoWise::InternalAPI::DOUBLE_SPLAT, MemoWise::InternalAPI::SPLAT_AND_DOUBLE_SPLAT
|
251
|
+
else
|
252
|
+
# NOTE: When benchmarking this implementation against something like:
|
253
|
+
#
|
254
|
+
# @_memo_wise.fetch(key) do
|
255
|
+
# ...
|
256
|
+
# end
|
257
|
+
#
|
258
|
+
# this implementation may sometimes perform worse than the above. This
|
259
|
+
# is because this case uses a more complex hash key (see
|
260
|
+
# `MemoWise::InternalAPI.key_str`), and hashing that key has less
|
261
|
+
# consistent performance. In general, this should still be faster for
|
262
|
+
# truthy results because `Hash#[]` generally performs hash lookups
|
263
|
+
# faster than `Hash#fetch`.
|
264
|
+
#
|
265
|
+
# NOTE: Ruby 2.6 and below, and TruffleRuby 3.0, break when we use
|
266
|
+
# `define_method(...) do |*args, **kwargs|`. Instead we must use the
|
267
|
+
# simpler `|*args|` pattern. We can't just do this always though
|
268
|
+
# because Ruby 2.7 and above require `|*args, **kwargs|` to work
|
269
|
+
# correctly.
|
270
|
+
# See: https://blog.saeloun.com/2019/10/07/ruby-2-7-keyword-arguments-redesign.html#ruby-26
|
271
|
+
# :nocov:
|
272
|
+
if RUBY_VERSION < "2.7" || RUBY_ENGINE == "truffleruby"
|
273
|
+
klass.send(:define_method, method_name) do |*args| # Ruby 2.4's `define_method` is private in some cases
|
274
|
+
index = MemoWise::InternalAPI.index(self, method_name)
|
275
|
+
klass.module_eval <<~HEREDOC, __FILE__, __LINE__ + 1
|
276
|
+
def #{method_name}(#{MemoWise::InternalAPI.args_str(method)})
|
277
|
+
_memo_wise_hash = (@_memo_wise[#{index}] ||= {})
|
278
|
+
_memo_wise_key = #{MemoWise::InternalAPI.key_str(method)}
|
279
|
+
_memo_wise_output = _memo_wise_hash[_memo_wise_key]
|
280
|
+
if _memo_wise_output || _memo_wise_hash.key?(_memo_wise_key)
|
281
|
+
_memo_wise_output
|
282
|
+
else
|
283
|
+
_memo_wise_hash[_memo_wise_key] = #{original_memo_wised_name}(#{MemoWise::InternalAPI.call_str(method)})
|
284
|
+
end
|
285
|
+
end
|
286
|
+
HEREDOC
|
287
|
+
|
288
|
+
klass.send(visibility, method_name)
|
289
|
+
send(method_name, *args)
|
290
|
+
end
|
291
|
+
# :nocov:
|
292
|
+
else # Ruby 2.7 and above break with (*args)
|
293
|
+
klass.define_method(method_name) do |*args, **kwargs|
|
294
|
+
index = MemoWise::InternalAPI.index(self, method_name)
|
295
|
+
klass.module_eval <<~HEREDOC, __FILE__, __LINE__ + 1
|
296
|
+
def #{method_name}(#{MemoWise::InternalAPI.args_str(method)})
|
297
|
+
_memo_wise_hash = (@_memo_wise[#{index}] ||= {})
|
298
|
+
_memo_wise_key = #{MemoWise::InternalAPI.key_str(method)}
|
299
|
+
_memo_wise_output = _memo_wise_hash[_memo_wise_key]
|
300
|
+
if _memo_wise_output || _memo_wise_hash.key?(_memo_wise_key)
|
301
|
+
_memo_wise_output
|
302
|
+
else
|
303
|
+
_memo_wise_hash[_memo_wise_key] = #{original_memo_wised_name}(#{MemoWise::InternalAPI.call_str(method)})
|
304
|
+
end
|
305
|
+
end
|
306
|
+
HEREDOC
|
307
|
+
|
308
|
+
klass.send(visibility, method_name)
|
309
|
+
send(method_name, *args, **kwargs)
|
224
310
|
end
|
225
|
-
|
311
|
+
end
|
226
312
|
end
|
227
313
|
|
228
314
|
klass.send(visibility, method_name)
|
@@ -248,8 +334,7 @@ module MemoWise # rubocop:disable Metrics/ModuleLength
|
|
248
334
|
# (`...` or `*args, **kwargs`), making reflection on method parameters
|
249
335
|
# useless without this.
|
250
336
|
def target.instance_method(symbol)
|
251
|
-
|
252
|
-
original_memo_wised_name = :"_memo_wise_original_#{symbol}"
|
337
|
+
original_memo_wised_name = MemoWise::InternalAPI.original_memo_wised_name(symbol)
|
253
338
|
|
254
339
|
super.tap do |curr_method|
|
255
340
|
# Start with calling the original `instance_method` on `symbol`,
|
@@ -341,7 +426,6 @@ module MemoWise # rubocop:disable Metrics/ModuleLength
|
|
341
426
|
# Example.method_called_times #=> nil
|
342
427
|
##
|
343
428
|
|
344
|
-
# rubocop:disable Layout/LineLength
|
345
429
|
##
|
346
430
|
# @!method self.reset_memo_wise(method_name = nil, *args, **kwargs)
|
347
431
|
# Implementation of {#reset_memo_wise} for class methods.
|
@@ -375,7 +459,6 @@ module MemoWise # rubocop:disable Metrics/ModuleLength
|
|
375
459
|
#
|
376
460
|
# Example.reset_memo_wise # reset "all methods" mode
|
377
461
|
##
|
378
|
-
# rubocop:enable Layout/LineLength
|
379
462
|
|
380
463
|
# Presets the memoized result for the given method to the result of the given
|
381
464
|
# block.
|
@@ -428,21 +511,34 @@ module MemoWise # rubocop:disable Metrics/ModuleLength
|
|
428
511
|
# ex.method_called_times #=> nil
|
429
512
|
#
|
430
513
|
def preset_memo_wise(method_name, *args, **kwargs)
|
431
|
-
unless block_given?
|
432
|
-
|
433
|
-
|
514
|
+
raise ArgumentError, "Pass a block as the value to preset for #{method_name}, #{args}" unless block_given?
|
515
|
+
|
516
|
+
MemoWise::InternalAPI.validate_memo_wised!(self, method_name)
|
517
|
+
|
518
|
+
method = method(MemoWise::InternalAPI.original_memo_wised_name(method_name))
|
519
|
+
method_arguments = MemoWise::InternalAPI.method_arguments(method)
|
520
|
+
index = MemoWise::InternalAPI.index(self, method_name)
|
521
|
+
|
522
|
+
if method_arguments == MemoWise::InternalAPI::NONE
|
523
|
+
@_memo_wise_sentinels[index] = true
|
524
|
+
@_memo_wise[index] = yield
|
525
|
+
return
|
434
526
|
end
|
435
527
|
|
436
|
-
|
437
|
-
api.validate_memo_wised!(method_name)
|
528
|
+
hash = (@_memo_wise[index] ||= {})
|
438
529
|
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
530
|
+
case method_arguments
|
531
|
+
when MemoWise::InternalAPI::ONE_REQUIRED_POSITIONAL then hash[args.first] = yield
|
532
|
+
when MemoWise::InternalAPI::ONE_REQUIRED_KEYWORD then hash[kwargs.first.last] = yield
|
533
|
+
when MemoWise::InternalAPI::SPLAT then hash[args] = yield
|
534
|
+
when MemoWise::InternalAPI::DOUBLE_SPLAT then hash[kwargs] = yield
|
535
|
+
when MemoWise::InternalAPI::MULTIPLE_REQUIRED
|
536
|
+
key = method.parameters.map.with_index do |(type, name), idx|
|
537
|
+
type == :req ? args[idx] : kwargs[name]
|
444
538
|
end
|
445
|
-
hash[
|
539
|
+
hash[key] = yield
|
540
|
+
else # MemoWise::InternalAPI::SPLAT_AND_DOUBLE_SPLAT
|
541
|
+
hash[[args, kwargs]] = yield
|
446
542
|
end
|
447
543
|
end
|
448
544
|
|
@@ -513,33 +609,64 @@ module MemoWise # rubocop:disable Metrics/ModuleLength
|
|
513
609
|
#
|
514
610
|
def reset_memo_wise(method_name = nil, *args, **kwargs)
|
515
611
|
if method_name.nil?
|
516
|
-
unless args.empty?
|
517
|
-
|
518
|
-
end
|
612
|
+
raise ArgumentError, "Provided args when method_name = nil" unless args.empty?
|
613
|
+
raise ArgumentError, "Provided kwargs when method_name = nil" unless kwargs.empty?
|
519
614
|
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
return @_memo_wise.clear
|
615
|
+
@_memo_wise.clear
|
616
|
+
@_memo_wise_sentinels.clear
|
617
|
+
return
|
525
618
|
end
|
526
619
|
|
527
|
-
unless method_name.is_a?(Symbol)
|
528
|
-
|
529
|
-
end
|
620
|
+
raise ArgumentError, "#{method_name.inspect} must be a Symbol" unless method_name.is_a?(Symbol)
|
621
|
+
raise ArgumentError, "#{method_name} is not a defined method" unless respond_to?(method_name, true)
|
530
622
|
|
531
|
-
|
532
|
-
raise ArgumentError, "#{method_name} is not a defined method"
|
533
|
-
end
|
623
|
+
MemoWise::InternalAPI.validate_memo_wised!(self, method_name)
|
534
624
|
|
535
|
-
|
536
|
-
|
625
|
+
method = method(MemoWise::InternalAPI.original_memo_wised_name(method_name))
|
626
|
+
method_arguments = MemoWise::InternalAPI.method_arguments(method)
|
627
|
+
index = MemoWise::InternalAPI.index(self, method_name)
|
537
628
|
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
@_memo_wise[
|
542
|
-
|
629
|
+
case method_arguments
|
630
|
+
when MemoWise::InternalAPI::NONE
|
631
|
+
@_memo_wise_sentinels[index] = nil
|
632
|
+
@_memo_wise[index] = nil
|
633
|
+
when MemoWise::InternalAPI::ONE_REQUIRED_POSITIONAL
|
634
|
+
if args.empty?
|
635
|
+
@_memo_wise[index]&.clear
|
636
|
+
else
|
637
|
+
@_memo_wise[index]&.delete(args.first)
|
638
|
+
end
|
639
|
+
when MemoWise::InternalAPI::ONE_REQUIRED_KEYWORD
|
640
|
+
if kwargs.empty?
|
641
|
+
@_memo_wise[index]&.clear
|
642
|
+
else
|
643
|
+
@_memo_wise[index]&.delete(kwargs.first.last)
|
644
|
+
end
|
645
|
+
when MemoWise::InternalAPI::SPLAT
|
646
|
+
if args.empty?
|
647
|
+
@_memo_wise[index]&.clear
|
648
|
+
else
|
649
|
+
@_memo_wise[index]&.delete(args)
|
650
|
+
end
|
651
|
+
when MemoWise::InternalAPI::DOUBLE_SPLAT
|
652
|
+
if kwargs.empty?
|
653
|
+
@_memo_wise[index]&.clear
|
654
|
+
else
|
655
|
+
@_memo_wise[index]&.delete(kwargs)
|
656
|
+
end
|
657
|
+
else # MemoWise::InternalAPI::MULTIPLE_REQUIRED, MemoWise::InternalAPI::SPLAT_AND_DOUBLE_SPLAT
|
658
|
+
if args.empty? && kwargs.empty?
|
659
|
+
@_memo_wise[index]&.clear
|
660
|
+
else
|
661
|
+
key = if method_arguments == MemoWise::InternalAPI::SPLAT_AND_DOUBLE_SPLAT
|
662
|
+
[args, kwargs]
|
663
|
+
else
|
664
|
+
method.parameters.map.with_index do |(type, name), i|
|
665
|
+
type == :req ? args[i] : kwargs[name] # rubocop:disable Metrics/BlockNesting
|
666
|
+
end
|
667
|
+
end
|
668
|
+
@_memo_wise[index]&.delete(key)
|
669
|
+
end
|
543
670
|
end
|
544
671
|
end
|
545
672
|
end
|
data/memo_wise.gemspec
CHANGED
@@ -36,6 +36,7 @@ Gem::Specification.new do |spec| # rubocop:disable Metrics/BlockLength
|
|
36
36
|
spec.require_paths = ["lib"]
|
37
37
|
|
38
38
|
spec.metadata = {
|
39
|
+
"rubygems_mfa_required" => "true",
|
39
40
|
"changelog_uri" => "https://github.com/panorama-ed/memo_wise/blob/main/CHANGELOG.md",
|
40
41
|
"source_code_uri" => "https://github.com/panorama-ed/memo_wise"
|
41
42
|
}
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: memo_wise
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Panorama Education
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2021-
|
14
|
+
date: 2021-12-10 00:00:00.000000000 Z
|
15
15
|
dependencies: []
|
16
16
|
description:
|
17
17
|
email:
|
@@ -39,9 +39,7 @@ files:
|
|
39
39
|
- LICENSE.txt
|
40
40
|
- README.md
|
41
41
|
- Rakefile
|
42
|
-
- benchmarks/.ruby-version
|
43
42
|
- benchmarks/Gemfile
|
44
|
-
- benchmarks/Gemfile.lock
|
45
43
|
- benchmarks/benchmarks.rb
|
46
44
|
- bin/console
|
47
45
|
- bin/setup
|
@@ -54,6 +52,7 @@ homepage: https://github.com/panorama-ed/memo_wise
|
|
54
52
|
licenses:
|
55
53
|
- MIT
|
56
54
|
metadata:
|
55
|
+
rubygems_mfa_required: 'true'
|
57
56
|
changelog_uri: https://github.com/panorama-ed/memo_wise/blob/main/CHANGELOG.md
|
58
57
|
source_code_uri: https://github.com/panorama-ed/memo_wise
|
59
58
|
post_install_message:
|
data/benchmarks/.ruby-version
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
3.0.0
|
data/benchmarks/Gemfile.lock
DELETED
@@ -1,29 +0,0 @@
|
|
1
|
-
PATH
|
2
|
-
remote: ..
|
3
|
-
specs:
|
4
|
-
memo_wise (0.4.0)
|
5
|
-
|
6
|
-
GEM
|
7
|
-
remote: https://rubygems.org/
|
8
|
-
specs:
|
9
|
-
benchmark-ips (2.9.1)
|
10
|
-
memoist (0.16.2)
|
11
|
-
memoized (1.0.2)
|
12
|
-
memoizer (1.0.3)
|
13
|
-
|
14
|
-
PLATFORMS
|
15
|
-
x86_64-darwin-19
|
16
|
-
x86_64-linux
|
17
|
-
|
18
|
-
DEPENDENCIES
|
19
|
-
benchmark-ips (= 2.9.1)
|
20
|
-
memo_wise!
|
21
|
-
memoist (= 0.16.2)
|
22
|
-
memoized (= 1.0.2)
|
23
|
-
memoizer (= 1.0.3)
|
24
|
-
|
25
|
-
RUBY VERSION
|
26
|
-
ruby 3.0.0p0
|
27
|
-
|
28
|
-
BUNDLED WITH
|
29
|
-
2.2.3
|