Skip to content

Commit

Permalink
Fixed a bug that overwrote existing self.included method definitions.
Browse files Browse the repository at this point in the history
There is a hack that dynamically defines self.inherited when memo_wise is called, but there was a bug that did not consider the case where an existing self.inherited existed, so this has been fixed.
And I also fixed a bug that defined an `#inherited` method on the instance.
  • Loading branch information
alpaca-tc committed Jan 23, 2024
1 parent 718a584 commit 67a8828
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 5 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ _No breaking changes!_
**Project enhancements:**

- Fixed a bug that overwrote existing self.extended method definitions. [[#324]](https://github.com/panorama-ed/memo_wise/pull/314)
- Fixed a bug that overwrote existing self.inherited method definitions. [[#325]](https://github.com/panorama-ed/memo_wise/pull/315)

## [v1.8.0](https://github.com/panorama-ed/memo_wise/compare/v1.7.0...v1.8.0) - 2023-10-25

Expand Down
21 changes: 16 additions & 5 deletions lib/memo_wise.rb
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,14 @@ def extended(base)
end
private_constant(:CreateMemoWiseStateOnExtended)

module CreateMemoWiseStateOnInherited
def inherited(subclass)
super
MemoWise::InternalAPI.create_memo_wise_state!(subclass)
end
end
private_constant(:CreateMemoWiseStateOnInherited)

# @private
#
# Private setup method, called automatically by `prepend MemoWise` in a class.
Expand Down Expand Up @@ -165,12 +173,15 @@ def memo_wise(method_name_or_hash)

# This ensures that a memoized method defined on a parent class can
# still be used in a child class.
klass.module_eval <<~HEREDOC, __FILE__, __LINE__ + 1
def inherited(subclass)
super
MemoWise::InternalAPI.create_memo_wise_state!(subclass)
if klass.is_a?(Class)
if klass.singleton_class?
klass.prepend(CreateMemoWiseStateOnInherited)
else
klass.singleton_class.prepend(CreateMemoWiseStateOnInherited)
end
HEREDOC
else
klass.prepend(CreateMemoWiseStateOnInherited)
end

raise ArgumentError, "#{method_name.inspect} must be a Symbol" unless method_name.is_a?(Symbol)

Expand Down
80 changes: 80 additions & 0 deletions spec/memo_wise_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -842,5 +842,85 @@ def no_args; end
expect(instance.instance_variable_get(:@extended_called)).to be(true)
end
end

context "with target defined self.inherited" do
context "when target is class" do
let(:klass) do
Class.new do
prepend MemoWise

def self.inherited(subclass)
subclass.instance_variable_set(:@inherited_called, true)
end

def no_args; end
memo_wise :no_args
end
end

it "calls defined self.inherited" do
expect(Class.new(klass).instance_variable_get(:@inherited_called)).to be(true)
end

it "doesn't define #inherited" do
expect(klass).to be_respond_to(:inherited)
expect(klass.new).to_not be_respond_to(:inherited)
end
end

context "when target is singleton class" do
let(:klass) do
Class.new do
class << self
prepend MemoWise

def inherited(subclass)
subclass.instance_variable_set(:@inherited_called, true)
end

def no_args; end
memo_wise :no_args
end
end
end

it "calls defined self.inherited" do
expect(Class.new(klass).instance_variable_get(:@inherited_called)).to be(true)
end

it "doesn't define #inherited" do
expect(klass).to be_respond_to(:inherited)
expect(klass.new).to_not be_respond_to(:inherited)
end
end

context "when target is module" do
let(:klass) do
mod = Module.new do
prepend MemoWise

def inherited(subclass)
subclass.instance_variable_set(:@inherited_called, true)
end

def no_args; end
memo_wise :no_args
end

klass = Class.new
klass.extend(mod)
klass
end

it "calls defined self.inherited" do
expect(Class.new(klass).instance_variable_get(:@inherited_called)).to be(true)
end

it "doesn't define #inherited" do
expect(klass).to be_respond_to(:inherited)
expect(klass.new).to_not be_respond_to(:inherited)
end
end
end
end
end

0 comments on commit 67a8828

Please sign in to comment.