memo_wise 1.0.0 → 1.4.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/.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
|