Moduleのincludeとextendまわりの自分用サンプル
基本
module Foo def self.included(base) base.extend ClassMethods base.__send__ :include, InstanceMethods end module ClassMethods # クラスメソッドの定義 end module InstanceMethods # インスタンスメソッドの定義 end end (Bar = Class.new).__send__ :include, Foo p Bar.ancestors #=> [Bar, Foo::InstanceMethods, Foo, Object, Kernel] p (class << Bar; self end).ancestors #=> [Foo::ClassMethods, Class, Module, Object, Kernel] p Bar.included_modules #=> [Foo::InstanceMethods, Foo, Kernel] p (class << Bar; self end).included_modules #=> [Foo::ClassMethods, Kernel]
Module#extended, Module#included
module SuperModule module ModuleMethods def self.extended(base) puts "#{self} was extended by #{base}" end end extend ModuleMethods module InstanceMethods def self.included(base) puts "#{self} was included by #{base}" end end include InstanceMethods end #=> SuperModule::ModuleMethods was extended by SuperModule #=> SuperModule::InstanceMethods was included by SuperModule
Rails pluginなど
(追記) class_eval撲滅
module UsefulModule def self.included(base) base.extend ClassMethods end module ClassMethods def activate_useful_module self.__send__ :include, UsefulModule::InstanceMethods end end module InstanceMethods # インスタンスメソッドの定義 end end ExistingClass.__send__ :include, UsefulModule # 時は流れて・・・ ExistingClass.activate_useful_module #=> ExistingClassのインスタンスはUsefulModuleの協力なメソッド群を利用できるようになった
(追記)
禁じ手
module ForbiddenModule def self.included(base) base.__send__ :include, InstanceMethods end module InstanceMethods def self.included(mod) puts "#{self} was included by #{mod}" candidate = instance_methods & mod.instance_methods(false) candidate.each do |method| mod.__send__ :remove_method, method end end # 強制的に上書きするインスタンスメソッドの定義 end end VictimClass.__send__ :include, ForbiddenModule