#--
# Author:: Tyler Rick
# Copyright:: Copyright (c) 2007 QualitySmith, Inc.
# License:: Ruby License
# Submit to Facets?:: Yes
# Developer notes::
# * Method name too long? Imagine if we wanted to string multiple calls together.
# * Ideas:
# * single_send
# * singleton_send
# * singleton_call
# * singleton
# * singsend
# * extend_send
# * extend_call
# * create_and_send
# * create_and_call
#++
class Object
# Creates a singleton method and then calls it.
#
# More specificaly, it extends +self+ with the methods from +moduule+ and then sends the supplied +message+ and +args+ (if any).
#
# Advantages:
# * Keeps things object-oriented. Better than having global/class methods.
# * ("whatever".ss(MyColorizer, :colorize).ss(SomeOtherClass, :another_class_method) instead of
# * SomeOtherClass::another_class_method(MyColorizer::colorize("whatever")))
# * Method calls are _listed_ in the order in which they are _called_.
# * Still lets you keep your methods in a namespace.
# * Doesn't clutter up the base classes with methods that are only useful within a very small context. The methods are only added to the objects you specify. So you can "use" the base class without cluttering up _all_ instances of the class with your methods.
# * Useful for cases where creating a subclass wouldn't help because the methods you are calling would still return instances of the base class.
#
# Disadvantages:
# * You have to have/create a *module* for the functions you want to use.
# * Can't just call .sigleton_send(self, :some_method) if you want to use +some_method+ that's defined in +self+.
# * So what do we call the module containing the "singleton method"? String::MyColorizer? MyColorizer::String? MyStringColorizer?
#
# Examples:
# "whatever".ss(MyColorizer, :colorize, :blue)
#
def singleton_send(moduule, message, *args)
self.extend(moduule)
self.send(message, *args)
end
alias_method :ss, :singleton_send
# Couldn't get this idea to work:
# def singleton_that_accepts_object(object, method_name, *args)
## #class << self
## #self.instance_eval do
## self.class.module_eval do
## define_method(:colorize2, object.class.instance_method(:colorize2))
## end
## # raises "TypeError: bind argument must be an instance of TheTest"
#
## object.class.instance_method(method_name).
## bind(self)
## # raises "TypeError: bind argument must be an instance of TheTest"
#
## self.class.extend(object.class)
## self.class.send(:include, object.class)
## # raises "TypeError: wrong argument type Class (expected Module)"
# self.send(method_name, *args)
# end
end
# _____ _
# |_ _|__ ___| |_
# | |/ _ \/ __| __|
# | | __/\__ \ |_
# |_|\___||___/\__|
#
=begin test
require 'test/unit'
module MyColorizer
def colorize(color = nil)
self + " (colorized in #{color})"
end
end
#module PresentationLayer
# create_module_method :to_currency do
# #...
# end
#end
class TheTest < Test::Unit::TestCase
def test_1
assert_equal "whatever (colorized in )", "whatever".ss(MyColorizer, :colorize)
assert_equal "whatever (colorized in blue)", "whatever".singleton_send(MyColorizer, :colorize, :blue)
end
# def test_singleton_that_accepts_object
# assert_equal "whatever (colorized in )", "whatever".singleton_that_accepts_object(self, :colorize2)
# assert_equal "whatever (colorized in blue)", "whatever".singleton_that_accepts_object(self, :colorize2, :blue)
# end
# def colorize2(color = nil)
# self + " (colorized2 in #{color})"
# end
end
=end