From 72d40af99e955dd5904cfb8edcb0606eb165c4cb Mon Sep 17 00:00:00 2001 From: Seb Jacobs Date: Wed, 4 Dec 2019 21:38:58 +0000 Subject: [PATCH] Fix regression introduced by frozen symbol fix There was a recent change [1] made to how punctuation is escaped to address an issue introduced by a proposal in Ruby 2.7 (which is to change the behaviour of `Symbol#to_s` so that it returns a frozen string) [2]. This ended up breaking support for calling the `memoize` method with a punctuated string [3], e.g. ```ruby class Dog extend Memoist def woof? true end memoize 'woof?' end ``` I have added an additional test which should prevent further regressions from being introduced. [1] a893ce6 [2] https://bugs.ruby-lang.org/issues/16150 [3] https://github.com/matthewrudy/memoist/issues/85 --- lib/memoist.rb | 4 +--- test/memoist_test.rb | 17 +++++++++++++++-- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/lib/memoist.rb b/lib/memoist.rb index fcd3141..c49e102 100644 --- a/lib/memoist.rb +++ b/lib/memoist.rb @@ -38,12 +38,10 @@ def self.unmemoized_prefix(identifier = nil) end def self.escape_punctuation(string) - string = string.to_s + string = string.is_a?(String) ? string.dup : string.to_s.dup return string unless string.end_with?('?'.freeze, '!'.freeze) - string = string.dup if string.frozen? - # A String can't end in both ? and ! if string.sub!(/\?\Z/, '_query'.freeze) else diff --git a/test/memoist_test.rb b/test/memoist_test.rb index 49a09d0..433f119 100644 --- a/test/memoist_test.rb +++ b/test/memoist_test.rb @@ -67,6 +67,12 @@ def age memoize :name, :age + def age? + @counter.call(:age?) + true + end + memoize 'age?' + def sleep(hours = 8) @counter.call(:sleep) hours @@ -272,6 +278,13 @@ def test_memoization_with_punctuation @person.unmemoize_all end + def test_memoization_when_memoize_is_called_with_punctuated_string + assert_equal true, @person.age? + + @person.memoize_all + @person.unmemoize_all + end + def test_memoization_flush_with_punctuation assert_equal true, @person.name? @person.flush_cache(:name?) @@ -344,11 +357,11 @@ def test_unmemoize_all end def test_all_memoized_structs - # Person memoize :age, :is_developer?, :memoize_protected_test, :name, :name?, :sleep, :update, :update_attributes + # Person memoize :age, :age?, :is_developer?, :memoize_protected_test, :name, :name?, :sleep, :update, :update_attributes # Student < Person memoize :name, :identifier => :student # Teacher < Person memoize :seniority - expected = %w[age is_developer? memoize_protected_test name name? sleep update update_attributes] + expected = %w[age age? is_developer? memoize_protected_test name name? sleep update update_attributes] structs = Person.all_memoized_structs assert_equal expected, structs.collect(&:memoized_method).collect(&:to_s).sort assert_equal '@_memoized_name', structs.detect { |s| s.memoized_method == :name }.ivar