Skip to content

Commit

Permalink
Add .memoized? method (#17)
Browse files Browse the repository at this point in the history
To check (externally) if method memoized or not.
  • Loading branch information
AlexWayfer authored and tycooon committed Oct 1, 2019
1 parent bce4943 commit 9197d25
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 0 deletions.
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,28 @@ a.call # => 42
a.call # => 42
```

Check if method is memoized:

```ruby
class A
include Memery

memoize def call
puts "calculating"
42
end

def execute
puts "non-memoized"
end
end

a = A.new

a.memoized?(:call) # => true
a.memoized?(:execute) # => false
```

## Difference with other gems
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:

Expand Down
7 changes: 7 additions & 0 deletions lib/memery.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,13 @@ def memoize(method_name, condition: nil, ttl: nil)
define_memoized_method!(method_name, condition: condition, ttl: ttl)
end

def memoized?(method_name)
return false unless defined?(@_memery_module)

@_memery_module.method_defined?(method_name) ||
@_memery_module.private_method_defined?(method_name)
end

private

def prepend_memery_module!
Expand Down
69 changes: 69 additions & 0 deletions spec/memery_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ class A
m_private
end

def not_memoized; end

memoize def m_nil
m_protected
end
Expand Down Expand Up @@ -67,6 +69,12 @@ module M
CALLS << :m
:m
end

def not_memoized; end

private

memoize def m_private; end
end

class C
Expand Down Expand Up @@ -95,6 +103,12 @@ class E
end
end

class F
include Memery

def m; end
end

RSpec.describe Memery do
subject(:a) { A.new }

Expand Down Expand Up @@ -254,4 +268,59 @@ class E
end
end
end

describe ".memoized?" do
subject { object.memoized?(method_name) }

context "class without memoized methods" do
let(:object) { F }
let(:method_name) { :m }

it { is_expected.to be false }
end

shared_examples "works correctly" do
context "public memoized method" do
let(:method_name) { :m }

it { is_expected.to be true }
end

context "private memoized method" do
let(:method_name) { :m_private }

it { is_expected.to be true }
end

context "non-memoized method" do
let(:method_name) { :not_memoized }

it { is_expected.to be false }
end

context "standard class method" do
let(:method_name) { :constants }

it { is_expected.to be false }
end

context "standard instance method" do
let(:method_name) { :to_s }

it { is_expected.to be false }
end
end

context "class" do
let(:object) { A }

include_examples "works correctly"
end

context "module" do
let(:object) { M }

include_examples "works correctly"
end
end
end

0 comments on commit 9197d25

Please sign in to comment.