module ShortCircuIt

Constants

VERSION

This constant is managed by spicerack

Attributes

owner[R]

Public Instance Methods

clear_all_memoization() click to toggle source

Clears all memoized values on the object

# File lib/short_circu_it/memoization_store.rb, line 37
def clear_all_memoization
  memoized_hash.clear
end
clear_memoization(*method_names) click to toggle source

Clears all cached values for the given method

@param *method_names [Symbol] The name of a memoized method @return [Boolean] True if a value was cleared, false if not

# File lib/short_circu_it/memoization_store.rb, line 32
def clear_memoization(*method_names)
  method_names.all? { |method_name| memoized_hash.delete(method_name.to_sym) }
end
inspect() click to toggle source
# File lib/short_circu_it/memoization_store.rb, line 41
def inspect
  "#<#{self.class} memoized: #{memoized_hash.keys.inspect}>"
end

Private Instance Methods

_memoization_observers() click to toggle source
# File lib/short_circu_it.rb, line 99
def _memoization_observers
  @_memoization_observers ||= {}
end
add_memoized_observers(method_name, observers) click to toggle source
# File lib/short_circu_it.rb, line 103
def add_memoized_observers(method_name, observers)
  # TODO: Raise an error if method has already been memoized? A warning maybe?
  self._memoization_observers = _memoization_observers.
    merge(method_name.to_sym => Array.wrap(observers).freeze).
    freeze
end
current_memoization_for_method(method_name) click to toggle source

@param method_name [Symbol] The name of a memoized method @return [Hash] A hash of memoized values for the current state of the observed objects for the given method.

# File lib/short_circu_it/memoization_store.rb, line 73
def current_memoization_for_method(method_name)
  memoization_for_method(method_name)[state_hash(method_name)] ||= {}
end
current_memoization_for_method?(method_name) click to toggle source

@param method_name [Symbol] The name of a memoized method @return [Boolean] True if there are any memoized values for the current state of the observed objects.

# File lib/short_circu_it/memoization_store.rb, line 79
def current_memoization_for_method?(method_name)
  memoization_for_method(method_name).key?(state_hash(method_name))
end
memoization_for_method(method_name) click to toggle source
# File lib/short_circu_it/memoization_store.rb, line 51
def memoization_for_method(method_name)
  memoized_hash[method_name] ||= {}
end
memoization_observers() click to toggle source
# File lib/short_circu_it.rb, line 28
def memoization_observers
  return _memoization_observers unless superclass.respond_to?(:memoization_observers)

  superclass.memoization_observers.merge(_memoization_observers)
end
memoization_store() click to toggle source

@return [ShortCircuIt::MemoizationStore]

# File lib/short_circu_it.rb, line 23
def memoization_store
  @memoization_store ||= MemoizationStore.new(self)
end
memoize(*method_names, observes: :itself) click to toggle source

@example

def expensive_method
  puts "doing some really expensive operation here!"
  "these datas are yuuge"
end
memoize :expensive_method

expensive_method
doing some really expensive operation here!
=> "these datas are yuuge"
expensive_method
=> "these datas are yuuge"

@example

def some_association
  SomeAssociation.find(some_association_id)
end
memoize :some_association, observes: :some_association_id

some_association_id = 1
some_association
* database stuff *
=> #<SomeAssociation:1234 id: 1>

some_association
* no database stuff *
=> #<SomeAssociation:1234 id: 1>

some_association_id = 2
some_association
* database stuff *
=> #<SomeAssociation:2468 id: 2>

@api public @param *method_names [Symbol] The name(s) of one or more methods to be memoized @param :observes [Symbol, Array<Symbol>]

A method or array of methods to be observed to determine memoization cache validity.
If any of the observed values change, the cached value will be invalidated.
By default, the object will observe itself.
Calls superclass method
# File lib/short_circu_it.rb, line 75
def memoize(*method_names, observes: :itself)
  method_names.map(&:to_sym).each do |method_name|
    add_memoized_observers(method_name, observes)

    around_method(
      method_name,
      prevent_double_wrapping_for: ShortCircuIt,
    ) do |*args, **opts|
      memoization_store.memoize(method_name, (args + [ opts ]).hash) do
        # TODO: replace with `super(*args, **opts)` when <= 2.6 support is dropped
        if RUBY_VERSION < "2.7" && opts.blank?
          super(*args)
        else
          super(*args, **opts)
        end
      end
    end
  end
end
memoized?(method_name, argument_hash) click to toggle source

@param method_name [Symbol] The name of the method to memoize @param argument_hash [Integer] The hash value of the arguments passed to the method @return [Boolean] True if the method has a current memoized value with the given arguments

# File lib/short_circu_it/memoization_store.rb, line 58
def memoized?(method_name, argument_hash)
  current_memoization_for_method?(method_name) && current_memoization_for_method(method_name).key?(argument_hash)
end
memoized_hash() click to toggle source
# File lib/short_circu_it/memoization_store.rb, line 47
def memoized_hash
  @memoized_hash ||= {}
end
memoized_value(method_name, argument_hash) click to toggle source

@param method_name [String] The name of the method to memoize @param argument_hash [Integer] The hash value of the arguments passed to the method @return [*] The value that has been memoized for the method/argument combination

# File lib/short_circu_it/memoization_store.rb, line 65
def memoized_value(method_name, argument_hash)
  raise NotMemoizedError unless memoized?(method_name, argument_hash)

  current_memoization_for_method(method_name)[argument_hash]
end
state_hash(method_name) click to toggle source

@param method_name [Symbol] The name of a memoized method @return [Integer] The hash value of all observed objects for the given method.

# File lib/short_circu_it/memoization_store.rb, line 85
def state_hash(method_name)
  memoization_observers[method_name].map { |observed_method| owner.public_send(observed_method) }.hash
end