introspection-0.0.3/0000755000004100000410000000000012277766050014456 5ustar www-datawww-dataintrospection-0.0.3/Rakefile0000644000004100000410000000032712277766050016125 0ustar www-datawww-datarequire "bundler" Bundler::GemHelper.install_tasks require "rake/testtask" Rake::TestTask.new do |t| t.libs << "test" t.test_files = FileList["test/**/*_test.rb"] t.verbose = true end task :default => :test introspection-0.0.3/Gemfile0000644000004100000410000000004712277766050015752 0ustar www-datawww-datasource 'https://rubygems.org' gemspec introspection-0.0.3/.travis.yml0000644000004100000410000000005512277766050016567 0ustar www-datawww-datarvm: - 1.8.7 - 1.9.3 - 2.0.0 - 2.1.0 introspection-0.0.3/COPYING.txt0000644000004100000410000000205712277766050016333 0ustar www-datawww-data== Licence (MIT) Copyright (c) 2011 James Mead Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.introspection-0.0.3/lib/0000755000004100000410000000000012277766050015224 5ustar www-datawww-dataintrospection-0.0.3/lib/introspection.rb0000644000004100000410000000024512277766050020452 0ustar www-datawww-datarequire "introspection/core_ext" require "introspection/receivers" require "introspection/method" require "introspection/snapshot" require "introspection/assertions"introspection-0.0.3/lib/introspection/0000755000004100000410000000000012277766050020124 5ustar www-datawww-dataintrospection-0.0.3/lib/introspection/core_ext.rb0000644000004100000410000000004712277766050022262 0ustar www-datawww-datarequire "introspection/core_ext/symbol"introspection-0.0.3/lib/introspection/core_ext/0000755000004100000410000000000012277766050021734 5ustar www-datawww-dataintrospection-0.0.3/lib/introspection/core_ext/symbol.rb0000644000004100000410000000035712277766050023573 0ustar www-datawww-dataclass Symbol # Standard in ruby 1.8.7+. See official documentation[http://ruby-doc.org/core-1.9/classes/Symbol.html] def to_proc Proc.new { |*args| args.shift.__send__(self, *args) } end unless :to_proc.respond_to?(:to_proc) end introspection-0.0.3/lib/introspection/snapshot.rb0000644000004100000410000000151712277766050022314 0ustar www-datawww-datarequire "introspection/receivers" require "metaclass" module Introspection class Snapshot attr_reader :methods def initialize(object) @methods = (object.receivers rescue []).map do |receiver| [:public, :protected, :private].map do |visibility| query_method = "#{visibility}_instance_methods" receiver.send(query_method, false).map do |method| unbound_method = receiver.instance_method(method) if unbound_method.owner.equal?(receiver) Method.new(unbound_method, visibility) end end.compact end end.flatten end def diff(other) { :added => other.methods - methods, :removed => methods - other.methods } end def changed?(other) diff(other).values.flatten.any? end end endintrospection-0.0.3/lib/introspection/change_detector.rb0000644000004100000410000000312312277766050023566 0ustar www-datawww-datarequire "introspection" require "instantiator" before_class_snapshots = {} before_instance_snapshots = {} ObjectSpace.each_object do |object| if Class === object next if Instantiator.unsupported_class?(object) object.instantiate end end ObjectSpace.each_object do |object| if Class === object next if Instantiator.unsupported_class?(object) before_class_snapshots[object] = Introspection::Snapshot.new(object) before_instance_snapshots[object] = Introspection::Snapshot.new(object.instantiate) end end class String def foo end def self.bar end end after_class_snapshots = {} after_instance_snapshots = {} ObjectSpace.each_object do |object| if Class === object next if Instantiator.unsupported_class?(object) after_class_snapshots[object] = Introspection::Snapshot.new(object) after_instance_snapshots[object] = Introspection::Snapshot.new(object.instantiate) end end before_instance_snapshots.each_key do |key| if after_instance_snapshots[key] if before_instance_snapshots[key].changed?(after_instance_snapshots[key]) p [key, :instance_method, before_instance_snapshots[key].diff(after_instance_snapshots[key])] end end end before_class_snapshots.each_key do |key| if after_class_snapshots[key] if before_class_snapshots[key].changed?(after_class_snapshots[key]) p [key, :class_method, before_class_snapshots[key].diff(after_class_snapshots[key])] end end end # => [String, :instance_method, {:removed=>[], :added=>[String#foo (public)]}] # => [String, :class_method, {:removed=>[], :added=>[##bar (public)]}] introspection-0.0.3/lib/introspection/version.rb0000644000004100000410000000005512277766050022136 0ustar www-datawww-datamodule Introspection VERSION = "0.0.3" end introspection-0.0.3/lib/introspection/method.rb0000644000004100000410000000116712277766050021736 0ustar www-datawww-datarequire "forwardable" module Introspection class Method extend Forwardable def_delegators :@method, :owner attr_reader :visibility def initialize(method, visibility = :public) @method, @visibility = method, visibility end def ==(other) (owner == other.owner) && (name == other.name) && (visibility == other.visibility) end def eql?(other) (self.class === other) && (self == other) end def hash [owner, name, visibility].hash end def name @method.name.to_sym end def inspect "#{owner}##{name} (#{visibility})" end end endintrospection-0.0.3/lib/introspection/receivers.rb0000644000004100000410000000140412277766050022437 0ustar www-datawww-datarequire "metaclass" module Introspection module Receivers class NullMetaclass def ancestors Array.new end end class NullReceiver def __metaclass__ NullMetaclass.new end def receivers Array.new end end def superklass respond_to?(:superclass) ? superclass : NullReceiver.new end def local_receivers receivers = [] receivers << __metaclass__ if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.1.0') receivers += __metaclass__.ancestors receivers -= superklass.__metaclass__.ancestors receivers end def receivers local_receivers + superklass.receivers end end end class Object include Introspection::Receivers endintrospection-0.0.3/lib/introspection/assertions.rb0000644000004100000410000000073012277766050022643 0ustar www-datawww-datamodule Introspection module Assertions def assert_snapshot_changed(object) before = Snapshot.new(object) yield after = Snapshot.new(object) assert before.changed?(after), "Snapshot has not changed." end def assert_snapshot_unchanged(object) before = Snapshot.new(object) yield after = Snapshot.new(object) assert !before.changed?(after), "Snapshot has changed: #{before.diff(after).inspect}" end end endintrospection-0.0.3/samples/0000755000004100000410000000000012277766050016122 5ustar www-datawww-dataintrospection-0.0.3/samples/class.rb0000644000004100000410000000272312277766050017560 0ustar www-datawww-datamodule Kernel def foo puts "Kernel#foo" super rescue NoMethodError end end class Object def foo puts "Object#foo" super rescue NoMethodError end def self.foo puts "Object.foo" super rescue NoMethodError end end class Module def foo puts "Module#foo" super rescue NoMethodError end end class Class def foo puts "Class#foo" super rescue NoMethodError end end module GreatUncle def foo puts "GreatUncle#foo" super rescue NoMethodError end end module GreatAunt def foo puts "GreatAunt#foo" super rescue NoMethodError end end class Grandaddy def self.foo puts "Grandaddy.foo" super rescue NoMethodError end extend GreatUncle, GreatAunt end module Uncle def foo puts "Uncle#foo" super rescue NoMethodError end end module Aunt def foo puts "Aunt#foo" super rescue NoMethodError end end class Daddy < Grandaddy def self.foo puts "Daddy.foo" super rescue NoMethodError end extend Uncle, Aunt end module Brother def foo puts "Brother#foo" super rescue NoMethodError end end module HalfSister def foo puts "HalfSister#foo" super rescue NoMethodError end end module Sister def foo puts "Sister#foo" super rescue NoMethodError end include HalfSister end class Sonny < Daddy def self.foo puts "Sonny.foo" super rescue NoMethodError end extend Brother, Sister end Sonny.foo introspection-0.0.3/samples/module.rb0000644000004100000410000000050112277766050017730 0ustar www-datawww-datamodule Grandaddy def foo puts "Grandaddy#foo" super rescue NoMethodError end end module Daddy def foo puts "Daddy#foo" super rescue NoMethodError end include Grandaddy end module Sonny def self.foo puts "Sonny.foo" super rescue NoMethodError end extend Daddy end Sonny.foointrospection-0.0.3/samples/instance.rb0000644000004100000410000000246612277766050020263 0ustar www-datawww-datamodule Kernel def foo puts "Kernel#foo" super rescue NoMethodError end end class Object def foo puts "Object#foo" super rescue NoMethodError end end module GreatUncle def foo puts "GreatUncle#foo" super rescue NoMethodError end end module GreatAunt def foo puts "GreatAunt#foo" super rescue NoMethodError end end class Grandaddy def foo puts "Grandaddy#foo" super rescue NoMethodError end include GreatUncle, GreatAunt end module Uncle def foo puts "Uncle#foo" super rescue NoMethodError end end module Aunt def foo puts "Aunt#foo" super rescue NoMethodError end end class Daddy < Grandaddy def foo puts "Daddy#foo" super rescue NoMethodError end include Uncle, Aunt end module Brother def foo puts "Brother#foo" super rescue NoMethodError end end module HalfSister def foo puts "HalfSister#foo" super rescue NoMethodError end end module Sister def foo puts "Sister#foo" super rescue NoMethodError end include HalfSister end class Sonny < Daddy def foo puts "Sonny#foo" super rescue NoMethodError end include Brother, Sister end sonny = Sonny.new class << sonny def foo puts "sonny#foo" super rescue NoMethodError end end sonny.foointrospection-0.0.3/metadata.yml0000644000004100000410000000606112277766050016764 0ustar www-datawww-data--- !ruby/object:Gem::Specification name: introspection version: !ruby/object:Gem::Version version: 0.0.3 platform: ruby authors: - James Mead autorequire: bindir: bin cert_chain: [] date: 2014-01-26 00:00:00.000000000 Z dependencies: - !ruby/object:Gem::Dependency name: metaclass requirement: !ruby/object:Gem::Requirement requirements: - - "~>" - !ruby/object:Gem::Version version: 0.0.1 type: :runtime prerelease: false version_requirements: !ruby/object:Gem::Requirement requirements: - - "~>" - !ruby/object:Gem::Version version: 0.0.1 - !ruby/object:Gem::Dependency name: instantiator requirement: !ruby/object:Gem::Requirement requirements: - - "~>" - !ruby/object:Gem::Version version: 0.0.3 type: :runtime prerelease: false version_requirements: !ruby/object:Gem::Requirement requirements: - - "~>" - !ruby/object:Gem::Version version: 0.0.3 - !ruby/object:Gem::Dependency name: rake requirement: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' type: :development prerelease: false version_requirements: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' - !ruby/object:Gem::Dependency name: blankslate requirement: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' type: :development prerelease: false version_requirements: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' description: '' email: - james@floehopper.org executables: [] extensions: [] extra_rdoc_files: [] files: - ".gitignore" - ".travis.yml" - COPYING.txt - Gemfile - README.md - Rakefile - introspection.gemspec - lib/introspection.rb - lib/introspection/assertions.rb - lib/introspection/change_detector.rb - lib/introspection/core_ext.rb - lib/introspection/core_ext/symbol.rb - lib/introspection/method.rb - lib/introspection/receivers.rb - lib/introspection/snapshot.rb - lib/introspection/version.rb - samples/class.rb - samples/instance.rb - samples/module.rb - test/class_snapshot_test.rb - test/instance_snapshot_test.rb - test/module_snapshot_test.rb - test/snapshot_test.rb - test/test_helper.rb homepage: http://jamesmead.org licenses: - MIT metadata: {} post_install_message: rdoc_options: [] require_paths: - lib required_ruby_version: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' required_rubygems_version: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: 1.3.6 requirements: [] rubyforge_project: introspection rubygems_version: 2.2.0 signing_key: specification_version: 4 summary: Dynamic inspection of the hierarchy of method definitions on a Ruby object. test_files: - test/class_snapshot_test.rb - test/instance_snapshot_test.rb - test/module_snapshot_test.rb - test/snapshot_test.rb - test/test_helper.rb introspection-0.0.3/test/0000755000004100000410000000000012277766050015435 5ustar www-datawww-dataintrospection-0.0.3/test/snapshot_test.rb0000644000004100000410000000325212277766050020662 0ustar www-datawww-datarequire "test_helper" require "blankslate" class SnapshotTest < Test::Unit::TestCase include Introspection def test_should_report_methods_added instance = Class.new.new before = Snapshot.new(instance) instance.__metaclass__.send(:define_method, :foo) {} after = Snapshot.new(instance) diff = before.diff(after) assert_equal 1, diff[:added].length assert_equal instance.__metaclass__, diff[:added][0].owner assert_equal :foo, diff[:added][0].name end def test_should_report_methods_removed instance = Class.new.new instance.__metaclass__.send(:define_method, :foo) {} before = Snapshot.new(instance) instance.__metaclass__.send(:remove_method, :foo) after = Snapshot.new(instance) diff = before.diff(after) assert_equal 1, diff[:removed].length assert_equal instance.__metaclass__, diff[:removed][0].owner assert_equal :foo, diff[:removed][0].name end def test_should_indicate_snapshot_has_changed_when_method_is_added instance = Class.new.new assert_snapshot_changed(instance) do instance.__metaclass__.send(:define_method, :foo) {} end end def test_should_indicate_snapshot_has_changed_when_method_is_removed instance = Class.new.new instance.__metaclass__.send(:define_method, :foo) {} assert_snapshot_changed(instance) do instance.__metaclass__.send(:remove_method, :foo) end end def test_should_indicate_snapshot_has_not_changed_when_method_no_methods_are_added_or_removed instance = Class.new.new assert_snapshot_unchanged(instance) {} end def test_should_cope_with_blankslate_object assert_nothing_raised { Snapshot.new(BlankSlate.new) } end endintrospection-0.0.3/test/class_snapshot_test.rb0000644000004100000410000000527312277766050022054 0ustar www-datawww-datarequire "test_helper" class ClassSnapshotTest < Test::Unit::TestCase def test_detect_class_method_on_class for_all_method_visibilities do |visibility| klass = Class.new klass.__metaclass__.send(:define_method, :foo) {} klass.__metaclass__.send(visibility, :foo) assert_method_exists(klass, klass.__metaclass__, :foo, visibility) end end def test_detect_class_method_on_superclass for_all_method_visibilities do |visibility| superklass = Class.new superklass.__metaclass__.send(:define_method, :foo) {} superklass.__metaclass__.send(visibility, :foo) klass = Class.new(superklass) assert_method_exists(klass, superklass.__metaclass__, :foo, visibility) end end def test_detect_class_method_on_superclass_of_superclass for_all_method_visibilities do |visibility| superduperklass = Class.new superduperklass.__metaclass__.send(:define_method, :foo) {} superduperklass.__metaclass__.send(visibility, :foo) klass = Class.new(Class.new(superduperklass)) assert_method_exists(klass, superduperklass.__metaclass__, :foo, visibility) end end def test_detect_method_on_module_included_as_class_method_into_class for_all_method_visibilities do |visibility| mod = Module.new mod.send(:define_method, :foo) {} mod.send(visibility, :foo) klass = Class.new do extend mod end assert_method_exists(klass, mod, :foo, visibility) end end def test_detect_method_on_module_included_as_class_method_into_superclass for_all_method_visibilities do |visibility| mod = Module.new mod.send(:define_method, :foo) {} mod.send(visibility, :foo) superklass = Class.new do extend mod end klass = Class.new(superklass) assert_method_exists(klass, mod, :foo, visibility) end end def test_detect_method_on_module_included_as_class_method_into_superclass_of_superclass for_all_method_visibilities do |visibility| mod = Module.new mod.send(:define_method, :foo) {} mod.send(visibility, :foo) superduperklass = Class.new do extend mod end klass = Class.new(Class.new(superduperklass)) assert_method_exists(klass, mod, :foo, visibility) end end def test_detect_method_on_module_included_into_module_included_as_class_method_into_class for_all_method_visibilities do |visibility| mod = Module.new mod.send(:define_method, :foo) {} mod.send(visibility, :foo) supermod = Module.new do include mod end klass = Class.new do extend supermod end assert_method_exists(klass, mod, :foo, visibility) end end endintrospection-0.0.3/test/module_snapshot_test.rb0000644000004100000410000000227612277766050022234 0ustar www-datawww-datarequire "test_helper" class ModuleSnapshotTest < Test::Unit::TestCase def test_detect_module_method_on_module for_all_method_visibilities do |visibility| mod = Module.new mod.__metaclass__.send(:define_method, :foo) {} mod.__metaclass__.send(visibility, :foo) assert_method_exists(mod, mod.__metaclass__, :foo, visibility) end end def test_detect_method_on_module_included_as_module_method_on_module for_all_method_visibilities do |visibility| supermod = Module.new supermod.send(:define_method, :foo) {} supermod.send(visibility, :foo) mod = Module.new do extend supermod end assert_method_exists(mod, supermod, :foo, visibility) end end def test_detect_method_on_module_included_into_module_included_as_module_method_on_module for_all_method_visibilities do |visibility| superdupermod = Module.new superdupermod.send(:define_method, :foo) {} superdupermod.send(visibility, :foo) supermod = Module.new do include superdupermod end mod = Module.new do extend supermod end assert_method_exists(mod, superdupermod, :foo, visibility) end end endintrospection-0.0.3/test/test_helper.rb0000644000004100000410000000146512277766050020306 0ustar www-datawww-datarequire "rubygems" require "bundler/setup" require "introspection" require "test/unit" module Introspection module TestHelper def for_all_method_visibilities(&block) [:public, :protected, :private].each do |visibility| block.call(visibility) end end end module LocalAssertions def assert_method_exists(object, owner, method_name, visibility) snapshot = Snapshot.new(object) method = owner.instance_method(method_name) expected_method = Method.new(method, visibility) methods_for_name = snapshot.methods.select { |m| m.name == method_name } assert_equal [expected_method], methods_for_name end end end class Test::Unit::TestCase include Introspection::TestHelper include Introspection::LocalAssertions include Introspection::Assertions endintrospection-0.0.3/test/instance_snapshot_test.rb0000644000004100000410000000741412277766050022552 0ustar www-datawww-datarequire "test_helper" class InstanceSnapshotTest < Test::Unit::TestCase def test_detect_instance_method_on_singleton_class for_all_method_visibilities do |visibility| instance = Class.new.new instance.__metaclass__.send(:define_method, :foo) {} instance.__metaclass__.send(visibility, :foo) assert_method_exists(instance, instance.__metaclass__, :foo, visibility) end end def test_detect_instance_method_on_module_included_into_singleton_class for_all_method_visibilities do |visibility| mod = Module.new mod.send(:define_method, :foo) {} mod.send(visibility, :foo) instance = Class.new.new instance.extend(mod) assert_method_exists(instance, mod, :foo, visibility) end end def test_detect_instance_method_on_module_included_module_included_into_singleton_class for_all_method_visibilities do |visibility| supermod = Module.new supermod.send(:define_method, :foo) {} supermod.send(visibility, :foo) mod = Module.new mod.send(:include, supermod) instance = Class.new.new instance.extend(mod) assert_method_exists(instance, supermod, :foo, visibility) end end def test_detect_instance_method_on_class for_all_method_visibilities do |visibility| klass = Class.new klass.send(:define_method, :foo) {} klass.send(visibility, :foo) instance = klass.new assert_method_exists(instance, klass, :foo, visibility) end end def test_detect_instance_method_on_superclass for_all_method_visibilities do |visibility| superklass = Class.new superklass.send(:define_method, :foo) {} superklass.send(visibility, :foo) instance = Class.new(superklass).new assert_method_exists(instance, superklass, :foo, visibility) end end def test_detect_instance_method_on_superclass_of_superclass for_all_method_visibilities do |visibility| superduperklass = Class.new superduperklass.send(:define_method, :foo) {} superduperklass.send(visibility, :foo) instance = Class.new(Class.new(superduperklass)).new assert_method_exists(instance, superduperklass, :foo, visibility) end end def test_detect_instance_method_on_module_included_into_class for_all_method_visibilities do |visibility| mod = Module.new mod.send(:define_method, :foo) {} mod.send(visibility, :foo) instance = Class.new do include mod end.new assert_method_exists(instance, mod, :foo, visibility) end end def test_detect_instance_method_on_module_included_into_superclass for_all_method_visibilities do |visibility| mod = Module.new mod.send(:define_method, :foo) {} mod.send(visibility, :foo) superklass = Class.new do include mod end instance = Class.new(superklass).new assert_method_exists(instance, mod, :foo, visibility) end end def test_detect_instance_method_on_module_included_into_superclass_of_superclass for_all_method_visibilities do |visibility| mod = Module.new mod.send(:define_method, :foo) {} mod.send(visibility, :foo) superduperklass = Class.new do include mod end instance = Class.new(Class.new(superduperklass)).new assert_method_exists(instance, mod, :foo, visibility) end end def test_detect_instance_method_on_module_included_into_module_included_into_class for_all_method_visibilities do |visibility| mod = Module.new mod.send(:define_method, :foo) {} mod.send(visibility, :foo) supermod = Module.new do include mod end klass = Class.new do include supermod end instance = klass.new assert_method_exists(instance, mod, :foo, visibility) end end endintrospection-0.0.3/introspection.gemspec0000644000004100000410000000203612277766050020724 0ustar www-datawww-data# -*- encoding: utf-8 -*- lib = File.expand_path('../lib/', __FILE__) $LOAD_PATH.unshift lib unless $LOAD_PATH.include?(lib) require "introspection/version" Gem::Specification.new do |s| s.name = "introspection" s.version = Introspection::VERSION s.platform = Gem::Platform::RUBY s.authors = ["James Mead"] s.email = ["james@floehopper.org"] s.homepage = "http://jamesmead.org" s.summary = %q{Dynamic inspection of the hierarchy of method definitions on a Ruby object.} s.description = %q{} s.license = "MIT" s.required_rubygems_version = ">= 1.3.6" s.rubyforge_project = "introspection" s.files = `git ls-files`.split("\n") s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) } s.require_paths = ["lib"] s.add_dependency "metaclass", "~> 0.0.1" s.add_dependency "instantiator", "~> 0.0.3" s.add_development_dependency "rake" s.add_development_dependency "blankslate" end introspection-0.0.3/.gitignore0000644000004100000410000000002012277766050016436 0ustar www-datawww-dataGemfile.lock pkgintrospection-0.0.3/checksums.yaml.gz0000444000004100000410000000041612277766050017745 0ustar www-datawww-datakRe)rdA Dy/ЎTZlOuG#߆Eq{_?/?_|Qfd\Ɛxq??~804 YWe֞E7)QnezIKNbx֮9bc%!HPE,5B ^3Hn}u+D̙n}s~%PX0b<(W/<%׵(zi)=(u0@0]Ha봋O$!introspection-0.0.3/README.md0000644000004100000410000000045112277766050015735 0ustar www-datawww-dataDynamic inspection of the hierarchy of method definitions on a Ruby object. Motivations :- * Extract code that may be generally useful from Mocha. * Learn more about the Ruby's Object, Class & Module and the method receiver chain. * Detect undesirable changes to classes made by other libraries.