lib/rspec/mocks/object_reference.rb
module RSpec module Mocks # @private class ObjectReference # Returns an appropriate Object or Module reference based # on the given argument. def self.for(object_module_or_name, allow_direct_object_refs=false) case object_module_or_name when Module if anonymous_module?(object_module_or_name) DirectObjectReference.new(object_module_or_name) else # Use a `NamedObjectReference` if it has a name because this # will use the original value of the constant in case it has # been stubbed. NamedObjectReference.new(name_of(object_module_or_name)) end when String NamedObjectReference.new(object_module_or_name) else if allow_direct_object_refs DirectObjectReference.new(object_module_or_name) else raise ArgumentError, "Module or String expected, got #{object_module_or_name.inspect}" end end end if Module.new.name.nil? def self.anonymous_module?(mod) !name_of(mod) end else # 1.8.7 def self.anonymous_module?(mod) name_of(mod) == "" end end private_class_method :anonymous_module? def self.name_of(mod) MODULE_NAME_METHOD.bind(mod).call end private_class_method :name_of # @private MODULE_NAME_METHOD = Module.instance_method(:name) end # An implementation of rspec-mocks' reference interface. # Used when an object is passed to {ExampleMethods#object_double}, or # an anonymous class or module is passed to {ExampleMethods#instance_double} # or {ExampleMethods#class_double}. # Represents a reference to that object. # @see NamedObjectReference class DirectObjectReference # @param object [Object] the object to which this refers def initialize(object) @object = object end # @return [String] the object's description (via `#inspect`). def description @object.inspect end # Defined for interface parity with the other object reference # implementations. Raises an `ArgumentError` to indicate that `as_stubbed_const` # is invalid when passing an object argument to `object_double`. def const_to_replace raise ArgumentError, "Can not perform constant replacement with an anonymous object." end # The target of the verifying double (the object itself). # # @return [Object] def target @object end # Always returns true for an object as the class is defined. # # @return [true] def defined? true end # Yields if the reference target is loaded, providing a generic mechanism # to optionally run a bit of code only when a reference's target is # loaded. # # This specific implementation always yields because direct references # are always loaded. # # @yield [Object] the target of this reference. def when_loaded yield @object end end # An implementation of rspec-mocks' reference interface. # Used when a string is passed to {ExampleMethods#object_double}, # and when a string, named class or named module is passed to # {ExampleMethods#instance_double}, or {ExampleMethods#class_double}. # Represents a reference to the object named (via a constant lookup) # by the string. # @see DirectObjectReference class NamedObjectReference # @param const_name [String] constant name def initialize(const_name) @const_name = const_name end # @return [Boolean] true if the named constant is defined, false otherwise. def defined? !!object end # @return [String] the constant name to replace with a double. def const_to_replace @const_name end alias description const_to_replace # @return [Object, nil] the target of the verifying double (the named object), or # nil if it is not defined. def target object end # Yields if the reference target is loaded, providing a generic mechanism # to optionally run a bit of code only when a reference's target is # loaded. # # @yield [Object] the target object def when_loaded yield object if object end private def object return @object if defined?(@object) @object = Constant.original(@const_name).original_value end end end end