62 lines
2.2 KiB
Ruby
62 lines
2.2 KiB
Ruby
module Hashie
|
|
module Extensions
|
|
module Mash
|
|
# Allow a Mash to properly respond to everything
|
|
#
|
|
# By default, Mashes only say they respond to methods for keys that exist
|
|
# in their key set or any of the affix methods (e.g. setter, underbang,
|
|
# etc.). This causes issues when you try to use them within a
|
|
# SimpleDelegator or bind to a method for a key that is unset.
|
|
#
|
|
# This extension allows a Mash to properly respond to `respond_to?` and
|
|
# `method` for keys that have not yet been set. This enables full
|
|
# compatibility with SimpleDelegator and thunk-oriented programming.
|
|
#
|
|
# There is a trade-off with this extension: it will run slower than a
|
|
# regular Mash; insertions and initializations with keys run approximately
|
|
# 20% slower and cost approximately 19KB of memory per class that you
|
|
# make permissive.
|
|
#
|
|
# @api public
|
|
# @example Make a new, permissively responding Mash subclass
|
|
# class PermissiveMash < Hashie::Mash
|
|
# include Hashie::Extensions::Mash::PermissiveRespondTo
|
|
# end
|
|
#
|
|
# mash = PermissiveMash.new(a: 1)
|
|
# mash.respond_to? :b #=> true
|
|
module PermissiveRespondTo
|
|
# The Ruby hook for behavior when including the module
|
|
#
|
|
# @api private
|
|
# @private
|
|
# @return void
|
|
def self.included(base)
|
|
base.instance_variable_set :@_method_cache, base.instance_methods
|
|
base.define_singleton_method(:method_cache) { @_method_cache }
|
|
end
|
|
|
|
# The Ruby hook for determining what messages a class might respond to
|
|
#
|
|
# @api private
|
|
# @private
|
|
def respond_to_missing?(_method_name, _include_private = false)
|
|
true
|
|
end
|
|
|
|
private
|
|
|
|
# Override the Mash logging behavior to account for permissiveness
|
|
#
|
|
# @api private
|
|
# @private
|
|
def log_collision?(method_key)
|
|
self.class.method_cache.include?(method_key) &&
|
|
!self.class.disable_warnings?(method_key) &&
|
|
!(regular_key?(method_key) || regular_key?(method_key.to_s))
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|