Skip to content

Commit 9197d25

Browse files
AlexWayfertycooon
authored andcommitted
Add .memoized? method (#17)
To check (externally) if method memoized or not.
1 parent bce4943 commit 9197d25

File tree

3 files changed

+98
-0
lines changed

3 files changed

+98
-0
lines changed

README.md

+22
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,28 @@ a.call # => 42
168168
a.call # => 42
169169
```
170170

171+
Check if method is memoized:
172+
173+
```ruby
174+
class A
175+
include Memery
176+
177+
memoize def call
178+
puts "calculating"
179+
42
180+
end
181+
182+
def execute
183+
puts "non-memoized"
184+
end
185+
end
186+
187+
a = A.new
188+
189+
a.memoized?(:call) # => true
190+
a.memoized?(:execute) # => false
191+
```
192+
171193
## Difference with other gems
172194
Memery is very similar to [Memoist](https://github.com/matthewrudy/memoist). The difference is that it doesn't override methods, instead it uses Ruby 2 `Module.prepend` feature. This approach is cleaner (for example you are able to inspect the original method body using `method(:x).super_method.source`) and it allows subclasses' methods to work properly: if you redefine a memoized method in a subclass, it's not memoized by default, but you can memoize it normally (without using awkward `identifier: ` argument) and it will just work:
173195

lib/memery.rb

+7
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,13 @@ def memoize(method_name, condition: nil, ttl: nil)
3131
define_memoized_method!(method_name, condition: condition, ttl: ttl)
3232
end
3333

34+
def memoized?(method_name)
35+
return false unless defined?(@_memery_module)
36+
37+
@_memery_module.method_defined?(method_name) ||
38+
@_memery_module.private_method_defined?(method_name)
39+
end
40+
3441
private
3542

3643
def prepend_memery_module!

spec/memery_spec.rb

+69
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ class A
1414
m_private
1515
end
1616

17+
def not_memoized; end
18+
1719
memoize def m_nil
1820
m_protected
1921
end
@@ -67,6 +69,12 @@ module M
6769
CALLS << :m
6870
:m
6971
end
72+
73+
def not_memoized; end
74+
75+
private
76+
77+
memoize def m_private; end
7078
end
7179

7280
class C
@@ -95,6 +103,12 @@ class E
95103
end
96104
end
97105

106+
class F
107+
include Memery
108+
109+
def m; end
110+
end
111+
98112
RSpec.describe Memery do
99113
subject(:a) { A.new }
100114

@@ -254,4 +268,59 @@ class E
254268
end
255269
end
256270
end
271+
272+
describe ".memoized?" do
273+
subject { object.memoized?(method_name) }
274+
275+
context "class without memoized methods" do
276+
let(:object) { F }
277+
let(:method_name) { :m }
278+
279+
it { is_expected.to be false }
280+
end
281+
282+
shared_examples "works correctly" do
283+
context "public memoized method" do
284+
let(:method_name) { :m }
285+
286+
it { is_expected.to be true }
287+
end
288+
289+
context "private memoized method" do
290+
let(:method_name) { :m_private }
291+
292+
it { is_expected.to be true }
293+
end
294+
295+
context "non-memoized method" do
296+
let(:method_name) { :not_memoized }
297+
298+
it { is_expected.to be false }
299+
end
300+
301+
context "standard class method" do
302+
let(:method_name) { :constants }
303+
304+
it { is_expected.to be false }
305+
end
306+
307+
context "standard instance method" do
308+
let(:method_name) { :to_s }
309+
310+
it { is_expected.to be false }
311+
end
312+
end
313+
314+
context "class" do
315+
let(:object) { A }
316+
317+
include_examples "works correctly"
318+
end
319+
320+
context "module" do
321+
let(:object) { M }
322+
323+
include_examples "works correctly"
324+
end
325+
end
257326
end

0 commit comments

Comments
 (0)