:pぴー.sendせんど(:pぴー, :pぴー)

mokoaki
mokoriso@gmail.com

2017/11/18

Rubyいわゆるフックメソッドまとめ

参考 Effective Ruby 項目28あたり

まとめないと覚えられない

Module

Module.included(class_or_module) include された
Module.prepended(class_or_module) prepend された
Module.extended(object) extend された

フックじゃないけどこちらに併記

Module.append_features include された時に実際に処理を行い、その後 included が呼び出される
Module.prepend_features prepend された時に実際に処理を行い、その後 prepended が呼び出される
Module.extend_object extend された時に実際に処理を行い、その後 extended が呼び出される
module M1
  class << self
    def included(class_or_module)
      super
      p "included: #{self}, #{class_or_module}"
    end

    def prepended(class_or_module)
      super
      p "prepended: #{self}, #{class_or_module}"
    end

    def extended(object)
      super
      p "extended: #{self}, #{object}"
    end

    def append_features(class_or_module)
      super
      p "append_features: #{self}, #{class_or_module}"
    end

    def prepend_features(class_or_module)
      super
      p "prepend_features: #{self}, #{class_or_module}"
    end

    def extend_object(object)
      super
      p "extend_object: #{self}, #{object}"
    end
  end
end

module M2
  include M1
  # => "append_features: M1, M2"
  # => "included: M1, M2"

  prepend M1
  # => "prepend_features: M1, M2"
  # => "prepended: M1, M2"

  extend M1
  # => "extend_object: M1, M2"
  # => "extended: M1, M2"
end

class C2
  include M1
  # => "append_features: M1, C2"
  # => "included: M1, C2"

  prepend M1
  # => "prepend_features: M1, C2"
  # => "prepended: M1, C2"

  extend M1
  # => "extend_object: M1, C2"
  # => "extended: M1, C2"
end

Class

Class.inherited(sub_class) 継承された(されそうだ)
class C1
  class << self
    def inherited(sub_class)
      super
      p "inherited: #{self}, #{sub_class}"
      p sub_class.instance_methods(false)
    end
  end
end

class C2 < C1
  def test_method
  end
end
# => "inherited: C1, C2"
# => []

p C2.instance_methods(false)
# => [:test_method]

Module or Class

Module_or_Class.method_added(method_name_sym) インスタンスメソッドが add された
Module_or_Class.method_removed(method_name_sym) インスタンスメソッドが remove された
Module_or_Class.method_undefined(method_name_sym) インスタンスメソッドが undef された
Module_or_Class.singleton_method_added(method_name_sym) 特異メソッドが add された
Module_or_Class.singleton_method_removed(method_name_sym) 特異メソッドが remove された
Module_or_Class.singleton_method_undefined(method_name_sym) 特異メソッドが undef された
module M1
  class << self
    def method_added(method_name_sym)
      super
      p "method_added: #{self} #{self.class} #{method_name_sym}"
    end

    def method_removed(method_name_sym)
      super
      p "method_removed: #{self} #{self.class} #{method_name_sym}"
    end

    def method_undefined(method_name_sym)
      super
      p "method_undefined: #{self} #{self.class} #{method_name_sym}"
    end
  end

  def method1
  end
  # => "method_added: M1 Module method1"

  define_method(:method2) do
  end
  # => "method_added: M1 Module method2"

  remove_method(:method1)
  # => "method_removed: M1 Module method1"

  undef_method(:method2)
  # => "method_undefined: M1 Module method2"
end
class C1
  class << self
    def method_added(method_name_sym)
      super
      p "method_added: #{self} #{self.class} #{method_name_sym}"
    end

    def method_removed(method_name_sym)
      super
      p "method_removed: #{self} #{self.class} #{method_name_sym}"
    end

    def method_undefined(method_name_sym)
      super
      p "method_undefined: #{self} #{self.class} #{method_name_sym}"
    end
  end

  def method3
  end
  # => "method_added: C1 Class method3"

  define_method(:method4) do
  end
  # => "method_added: C1 Class method4"

  remove_method(:method3)
  # => "method_removed: C1 Class method3"

  undef_method(:method4)
  # => "method_undefined: C1 Class method4"
end
module M1
  class << self
    def singleton_method_added(method_name_sym)
      super
      p "singleton_method_added: #{self} #{self.class} #{method_name_sym}"
    end
    # => "singleton_method_added: M1 Module singleton_method_added"

    def singleton_method_removed(method_name_sym)
      super
      p "singleton_method_removed: #{self} #{self.class} #{method_name_sym}"
    end
    # => "singleton_method_added: M1 Module singleton_method_removed"

    def singleton_method_undefined(method_name_sym)
      super
      p "singleton_method_undefined: #{self} #{self.class} #{method_name_sym}"
    end
    # => "singleton_method_added: M1 Module singleton_method_undefined"
  end

  class << self
    def method1
    end
    # => "singleton_method_added: M1 Module method1"
  end

  define_singleton_method(:method2) do
  end
  # => "singleton_method_added: M1 Module method2"

  class << self
    remove_method(:method1)
    # => "singleton_method_removed: M1 Module method1"
  end

  class << self
    undef_method(:method2)
    # => "singleton_method_undefined: M1 Module method2"
  end
end
module C1
  class << self
    def singleton_method_added(method_name_sym)
      super
      p "singleton_method_added: #{self} #{self.class} #{method_name_sym}"
    end
    # => "singleton_method_added: C1 Module singleton_method_added"

    def singleton_method_removed(method_name_sym)
      super
      p "singleton_method_removed: #{self} #{self.class} #{method_name_sym}"
    end
    # => "singleton_method_added: C1 Module singleton_method_removed"

    def singleton_method_undefined(method_name_sym)
      super
      p "singleton_method_undefined: #{self} #{self.class} #{method_name_sym}"
    end
    # => "singleton_method_added: C1 Module singleton_method_undefined"
  end

  class << self
    def method3
    end
    # => "singleton_method_added: C1 Module method3"
  end

  define_singleton_method(:method4) do
  end
  # => "singleton_method_added: C1 Module method4"

  class << self
    remove_method(:method3)
    # => "singleton_method_removed: C1 Module method3"
  end

  class << self
    undef_method(:method4)
    # => "singleton_method_undefined: C1 Module method4"
  end
end