#-- # 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