diff --git a/lib/memoist.rb b/lib/memoist.rb index 54b67e6..e3f8339 100644 --- a/lib/memoist.rb +++ b/lib/memoist.rb @@ -3,6 +3,34 @@ require 'memoist/version' module Memoist + OPERATOR_METHOD_NAMES = { + '[]': '__ELEMENT_ACCESS_OP__', + '[]=': '__ELEMENT_ASSIGNMENT_OP__', + '**': '__EXPOENTIATION_OP__', + '!': '__NEGATION_BANG_OP__', + '~': '__COMPLEMENT_OP__', + '+@': '__UNARY_PLUS_OP__', + '-@': '__UNARY_MINUS_OP__', + '*': '__MULTIPLICATION_OP__', + '/': '__DIVISION_OP__', + '%': '__MODULO_OP__', + '+': '__PLUS_OP__', + '-': '__MINUS_OP__', + '>>': '__BITWISE_SHIFT_RIGHT_OP__', + '<<': '__BITWISE_SHIFT_LEFT_OP__', + '&': '__BITWISE_AND_OP__', + '^': '__BITWISE_EXCLUSIVE_OR_OP__', + '|': '__BITWISE_OR_OP__', + '<=': '__LTE_OP__', + '<': '__LT_OP__', + '>': '__GT_OP__', + '>=': '__GTE_OP__', + '<=>': '__SPACESHIP_OP__', + '==': '__EQUALITY_OP__', + '===': '__TRIPLE_EQUALITY_OP__', + '=~': '__MATCH_OP__', + }.freeze + def self.extended(extender) Memoist.memoist_eval(extender) do unless singleton_class.method_defined?(:memoized_methods) @@ -14,11 +42,11 @@ def self.memoized_methods end def self.memoized_ivar_for(method_name, identifier = nil) - "@#{memoized_prefix(identifier)}_#{escape_punctuation(method_name)}" + "@#{memoized_prefix(identifier)}_#{escape_punctuation(OPERATOR_METHOD_NAMES.fetch(method_name, method_name))}" end def self.unmemoized_method_for(method_name, identifier = nil) - "#{unmemoized_prefix(identifier)}_#{method_name}".to_sym + "#{unmemoized_prefix(identifier)}_#{OPERATOR_METHOD_NAMES.fetch(method_name, method_name)}".to_sym end def self.memoized_prefix(identifier = nil) diff --git a/test/memoist_test.rb b/test/memoist_test.rb index 49a09d0..6dbe40a 100644 --- a/test/memoist_test.rb +++ b/test/memoist_test.rb @@ -130,6 +130,40 @@ def name end end + class OperatorMethods + extend Memoist + + OPERATORS = %w{ + [] []= + ** + ! ~ +@ -@ + * / % + + - + >> << + & + ^ | + <= < > >= + <=> + == === =~ + }.freeze + + attr_reader :counter + + def initialize + @counter = CallCounter.new + end + + OPERATORS.each do |operator| + class_eval(<<-EOS, __FILE__, __LINE__ + 1) + def #{operator}(other) + @counter.call(#{operator.inspect}) + 'foo' + end + memoize :#{operator} + EOS + end + end + module Rates extend Memoist @@ -547,4 +581,16 @@ def test_private_method_memoization assert_equal 'Yes', person.send(:is_developer?) assert_equal 1, person.is_developer_calls end + + def test_operator_method_names + operator_methods = OperatorMethods.new + + OperatorMethods::OPERATORS.each do |operator| + 3.times { operator_methods.send(operator, 'bar') } + + assert_equal 1, operator_methods.counter.count(operator) + assert_equal 'foo', operator_methods.send(operator, 'bar', :reload) + assert_equal 2, operator_methods.counter.count(operator) + end + end end