memoist 0.13.0 → 0.14.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/lib/memoist.rb +41 -17
- data/lib/memoist/version.rb +1 -1
- data/test/memoist_test.rb +93 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: aca25d96c69122d50102f2d9615409389004002e
|
4
|
+
data.tar.gz: db741378eab95d22ee2b6e6b9cde18fb4ec2abdb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1307707c8feba8c316cb1628503b76fde33e5c04b62de897c6350edc67333f325d652b45b614ecb4365229e909c7869e71c2713272b971826f8e33c7ddcbb566
|
7
|
+
data.tar.gz: 8b8141373347a9b87b7923fca58c3d3fb1daaa660af63ca765d1f9654343a77dbd915b3a8e0b89188870222a3d85cf8c9e9dba4d2af638cda4a63c50530c2acd
|
data/lib/memoist.rb
CHANGED
@@ -3,7 +3,7 @@ require 'memoist/core_ext/singleton_class'
|
|
3
3
|
module Memoist
|
4
4
|
|
5
5
|
def self.memoized_ivar_for(method_name, identifier=nil)
|
6
|
-
"@#{memoized_prefix(identifier)}_#{escape_punctuation(method_name
|
6
|
+
"@#{memoized_prefix(identifier)}_#{escape_punctuation(method_name)}"
|
7
7
|
end
|
8
8
|
|
9
9
|
def self.unmemoized_method_for(method_name, identifier=nil)
|
@@ -27,9 +27,9 @@ module Memoist
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def self.escape_punctuation(string)
|
30
|
-
|
30
|
+
string = string.is_a?(String) ? string.dup : string.to_s
|
31
31
|
|
32
|
-
string
|
32
|
+
return string unless string.end_with?('?'.freeze, '!'.freeze)
|
33
33
|
|
34
34
|
# A String can't end in both ? and !
|
35
35
|
if string.sub!(/\?\Z/, '_query'.freeze)
|
@@ -63,28 +63,52 @@ module Memoist
|
|
63
63
|
flush_cache
|
64
64
|
end
|
65
65
|
|
66
|
+
def memoized_structs(names)
|
67
|
+
structs = self.class.all_memoized_structs
|
68
|
+
return structs if names.empty?
|
69
|
+
|
70
|
+
structs.select { |s| names.include?(s.memoized_method) }
|
71
|
+
end
|
72
|
+
|
66
73
|
def prime_cache(*method_names)
|
67
|
-
method_names
|
68
|
-
|
69
|
-
|
70
|
-
__send__(method_name)
|
74
|
+
memoized_structs(method_names).each do |struct|
|
75
|
+
if struct.arity == 0
|
76
|
+
__send__(struct.memoized_method)
|
71
77
|
else
|
72
|
-
ivar
|
73
|
-
instance_variable_set(ivar, {})
|
78
|
+
instance_variable_set(struct.ivar, {})
|
74
79
|
end
|
75
80
|
end
|
76
81
|
end
|
77
82
|
|
78
83
|
def flush_cache(*method_names)
|
79
|
-
method_names
|
84
|
+
memoized_structs(method_names).each do |struct|
|
85
|
+
remove_instance_variable(struct.ivar) if instance_variable_defined?(struct.ivar)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
MemoizedMethod = Struct.new(:memoized_method, :ivar, :arity)
|
91
|
+
|
92
|
+
def all_memoized_structs
|
93
|
+
@all_memoized_structs ||= begin
|
94
|
+
structs = memoized_methods.dup
|
80
95
|
|
81
|
-
|
82
|
-
|
83
|
-
|
96
|
+
# Collect the memoized_methods of ancestors in ancestor order
|
97
|
+
# unless we already have it since self or parents could be overriding
|
98
|
+
# an ancestor method.
|
99
|
+
ancestors.grep(Memoist).each do |ancestor|
|
100
|
+
ancestor.memoized_methods.each do |m|
|
101
|
+
structs << m unless structs.any? {|am| am.memoized_method == m.memoized_method }
|
102
|
+
end
|
84
103
|
end
|
104
|
+
structs
|
85
105
|
end
|
86
106
|
end
|
87
107
|
|
108
|
+
def clear_structs
|
109
|
+
@all_memoized_structs = nil
|
110
|
+
end
|
111
|
+
|
88
112
|
def memoize(*method_names)
|
89
113
|
if method_names.last.is_a?(Hash)
|
90
114
|
identifier = method_names.pop[:identifier]
|
@@ -92,8 +116,7 @@ module Memoist
|
|
92
116
|
|
93
117
|
Memoist.memoist_eval(self) do
|
94
118
|
def self.memoized_methods
|
95
|
-
|
96
|
-
@_memoized_methods ||= Set.new
|
119
|
+
@_memoized_methods ||= []
|
97
120
|
end
|
98
121
|
end
|
99
122
|
|
@@ -110,8 +133,9 @@ module Memoist
|
|
110
133
|
end
|
111
134
|
alias_method unmemoized_method, method_name
|
112
135
|
|
113
|
-
|
114
|
-
|
136
|
+
mm = MemoizedMethod.new(method_name, memoized_ivar, instance_method(method_name).arity)
|
137
|
+
self.memoized_methods << mm
|
138
|
+
if mm.arity == 0
|
115
139
|
|
116
140
|
# define a method like this;
|
117
141
|
|
data/lib/memoist/version.rb
CHANGED
data/test/memoist_test.rb
CHANGED
@@ -114,6 +114,13 @@ class MemoistTest < Minitest::Test
|
|
114
114
|
memoize :name, :identifier => :student
|
115
115
|
end
|
116
116
|
|
117
|
+
class Teacher < Person
|
118
|
+
def seniority
|
119
|
+
"very_senior"
|
120
|
+
end
|
121
|
+
memoize :seniority
|
122
|
+
end
|
123
|
+
|
117
124
|
class Company
|
118
125
|
attr_reader :name_calls
|
119
126
|
def initialize
|
@@ -261,11 +268,75 @@ class MemoistTest < Minitest::Test
|
|
261
268
|
assert_equal 2, @calculator.counter
|
262
269
|
end
|
263
270
|
|
271
|
+
def test_all_memoized_structs
|
272
|
+
# Person memoize :age, :is_developer?, :memoize_protected_test, :name, :name?, :sleep, :update, :update_attributes
|
273
|
+
# Student < Person memoize :name, :identifier => :student
|
274
|
+
# Teacher < Person memoize :seniority
|
275
|
+
|
276
|
+
expected = %w(age is_developer? memoize_protected_test name name? sleep update update_attributes)
|
277
|
+
structs = Person.all_memoized_structs
|
278
|
+
assert_equal expected, structs.collect(&:memoized_method).collect(&:to_s).sort
|
279
|
+
assert_equal "@_memoized_name", structs.detect {|s| s.memoized_method == :name }.ivar
|
280
|
+
|
281
|
+
# Same expected methods
|
282
|
+
structs = Student.all_memoized_structs
|
283
|
+
assert_equal expected, structs.collect(&:memoized_method).collect(&:to_s).sort
|
284
|
+
assert_equal "@_memoized_student_name", structs.detect {|s| s.memoized_method == :name }.ivar
|
285
|
+
|
286
|
+
expected = (expected << "seniority").sort
|
287
|
+
structs = Teacher.all_memoized_structs
|
288
|
+
assert_equal expected, structs.collect(&:memoized_method).collect(&:to_s).sort
|
289
|
+
assert_equal "@_memoized_name", structs.detect {|s| s.memoized_method == :name }.ivar
|
290
|
+
end
|
291
|
+
|
292
|
+
def test_unmemoize_all_subclasses
|
293
|
+
# Person memoize :age, :is_developer?, :memoize_protected_test, :name, :name?, :sleep, :update, :update_attributes
|
294
|
+
# Student < Person memoize :name, :identifier => :student
|
295
|
+
# Teacher < Person memoize :seniority
|
296
|
+
|
297
|
+
teacher = Teacher.new
|
298
|
+
assert_equal "Josh", teacher.name
|
299
|
+
assert_equal "Josh", teacher.instance_variable_get(:@_memoized_name)
|
300
|
+
assert_equal "very_senior", teacher.seniority
|
301
|
+
assert_equal "very_senior", teacher.instance_variable_get(:@_memoized_seniority)
|
302
|
+
|
303
|
+
teacher.unmemoize_all
|
304
|
+
assert_nil teacher.instance_variable_get(:@_memoized_name)
|
305
|
+
assert_nil teacher.instance_variable_get(:@_memoized_seniority)
|
306
|
+
|
307
|
+
student = Student.new
|
308
|
+
assert_equal "Student Josh", student.name
|
309
|
+
assert_equal "Student Josh", student.instance_variable_get(:@_memoized_student_name)
|
310
|
+
assert_nil student.instance_variable_get(:@_memoized_seniority)
|
311
|
+
|
312
|
+
student.unmemoize_all
|
313
|
+
assert_nil student.instance_variable_get(:@_memoized_student_name)
|
314
|
+
end
|
315
|
+
|
264
316
|
def test_memoize_all
|
265
317
|
@calculator.memoize_all
|
266
318
|
assert @calculator.instance_variable_defined?(:@_memoized_counter)
|
267
319
|
end
|
268
320
|
|
321
|
+
def test_memoize_all_subclasses
|
322
|
+
# Person memoize :age, :is_developer?, :memoize_protected_test, :name, :name?, :sleep, :update, :update_attributes
|
323
|
+
# Student < Person memoize :name, :identifier => :student
|
324
|
+
# Teacher < Person memoize :seniority
|
325
|
+
|
326
|
+
teacher = Teacher.new
|
327
|
+
teacher.memoize_all
|
328
|
+
|
329
|
+
assert_equal "very_senior", teacher.instance_variable_get(:@_memoized_seniority)
|
330
|
+
assert_equal "Josh", teacher.instance_variable_get(:@_memoized_name)
|
331
|
+
|
332
|
+
student = Student.new
|
333
|
+
student.memoize_all
|
334
|
+
|
335
|
+
assert_equal "Student Josh", student.instance_variable_get(:@_memoized_student_name)
|
336
|
+
assert_equal "Student Josh", student.name
|
337
|
+
assert_nil student.instance_variable_get(:@_memoized_seniority)
|
338
|
+
end
|
339
|
+
|
269
340
|
def test_memoization_cache_is_different_for_each_instance
|
270
341
|
assert_equal 1, @calculator.counter
|
271
342
|
assert_equal 2, @calculator.counter(:reload)
|
@@ -331,7 +402,29 @@ class MemoistTest < Minitest::Test
|
|
331
402
|
end
|
332
403
|
|
333
404
|
def test_double_memoization_with_identifier
|
405
|
+
# Person memoize :age, :is_developer?, :memoize_protected_test, :name, :name?, :sleep, :update, :update_attributes
|
406
|
+
# Student < Person memoize :name, :identifier => :student
|
407
|
+
# Teacher < Person memoize :seniority
|
408
|
+
|
334
409
|
Person.memoize :name, :identifier => :again
|
410
|
+
p = Person.new
|
411
|
+
assert_equal "Josh", p.name
|
412
|
+
assert p.instance_variable_get(:@_memoized_again_name)
|
413
|
+
|
414
|
+
# HACK: tl;dr: Don't memoize classes in test that are used elsewhere.
|
415
|
+
# Calling Person.memoize :name, :identifier => :again pollutes Person
|
416
|
+
# and descendents since we cache the memoized method structures.
|
417
|
+
# This populates those structs, verifies Person is polluted, resets the
|
418
|
+
# structs, cleans up cached memoized_methods
|
419
|
+
Student.all_memoized_structs
|
420
|
+
Person.all_memoized_structs
|
421
|
+
Teacher.all_memoized_structs
|
422
|
+
assert Person.memoized_methods.any? { |m| m.ivar == "@_memoized_again_name" }
|
423
|
+
|
424
|
+
[Student, Teacher, Person].each { |obj| obj.clear_structs }
|
425
|
+
assert Person.memoized_methods.reject! { |m| m.ivar == "@_memoized_again_name" }
|
426
|
+
assert_nil Student.memoized_methods.reject! { |m| m.ivar == "@_memoized_again_name" }
|
427
|
+
assert_nil Teacher.memoized_methods.reject! { |m| m.ivar == "@_memoized_again_name" }
|
335
428
|
end
|
336
429
|
|
337
430
|
def test_memoization_with_a_subclass
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: memoist
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.14.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Joshua Peek
|
@@ -19,7 +19,7 @@ authors:
|
|
19
19
|
autorequire:
|
20
20
|
bindir: bin
|
21
21
|
cert_chain: []
|
22
|
-
date: 2015-
|
22
|
+
date: 2015-12-15 00:00:00.000000000 Z
|
23
23
|
dependencies:
|
24
24
|
- !ruby/object:Gem::Dependency
|
25
25
|
name: bundler
|
@@ -120,3 +120,4 @@ summary: memoize methods invocation
|
|
120
120
|
test_files:
|
121
121
|
- test/memoist_test.rb
|
122
122
|
- test/test_helper.rb
|
123
|
+
has_rdoc:
|