Skip to content

Instantly share code, notes, and snippets.

@lnznt
Created January 26, 2015 10:18
Show Gist options
  • Save lnznt/feb9b4e5683bd59d9c9e to your computer and use it in GitHub Desktop.
Save lnznt/feb9b4e5683bd59d9c9e to your computer and use it in GitHub Desktop.
Ruby: Module.#prepend でメソッド呼び出しをフック ref: http://qiita.com/lnznt/items/5653f04749c9f82f7021
p C.ancestors #=> [C::Logging, C, Object, Kernel, BasicObject]
$ ruby try1.rb
hook: hello # hook の出力
hello
$ ruby tx.rb
hook2: before!: hello # 2つ目のhookの出力
before!: hello # 1つ目のhookの出力
hello
after!: hello # 1つ目のhookの出力
hook2: after!: hello # 2つ目のhookの出力
p C.ancestors #=> [#<Module:0x007fac4fdb7510>, #<Module:0x007fac4fdb7628>, C, Object, Kernel, BasicObject]
$ ruby try3.rb
hello
goodbye
class C
module Logging # 名前(Logging)を付けて、素直にモジュール定義する
extend Forwardable
attr_writer :logger
def logger ; @logger ||= Logger.new(nil) ; end
delegate %i(debug info warn error fatal) => :logger
:
end
prepend Logging # prepend する
:
module Hook
def hook(&block)
module_eval { prepend Module.new &block }
end
end
class Class
include Hook
end
# Logfile created on 2015-01-26 00:39:51 +0900 by logger.rb/44203
I, [2015-01-26T00:50:39.131894 #19689] INFO -- : call 'foo(hello)'
I, [2015-01-26T00:50:39.132019 #19689] INFO -- : call 'bar(goodbye)'
class C
hook do # hook 設定
def foo(message)
puts "hook: #{message}"
super
end
end
def foo(message)
puts message
end
end
obj = C.new
obj.foo("hello")
class C
hook do # 1つ目のhook 設定
def foo(message)
puts "#{before_message}: #{message}"
super
puts "#{after_message}: #{message}"
end
end
hook do # 2つ目のhook 設定
def foo(message)
puts "hook2: #{before_message}: #{message}"
super
puts "hook2: #{after_message}: #{message}"
end
end
def foo(message)
puts message
end
def before_message
"before!"
end
def after_message
"after!"
end
end
c = C.new
c.foo("hello")
require 'forwardable'
require 'logger'
class C
hook do # ロギング <-- このコメントが必要なところに'不吉な匂い'が... (「おわりに」で述べます)
extend Forwardable
attr_writer :logger
def logger ; @logger ||= Logger.new(nil) ; end
delegate %i(debug info warn error fatal) => :logger
def foo(message)
info { "call 'foo(#{message})'" } # ログ出力
super
end
def bar(message)
info { "call 'bar(#{message})'" } # ログ出力
super
end
end
def foo(message)
puts message
end
def bar(message)
puts message
end
end
c = C.new
c.logger = Logger.new 'try.log'
c.foo("hello")
c.bar("goodbye")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment