我是ruby的新手
尝试写一个方面。我的代码如下
我的代码如下
module Utils
module Aspects
def self.included(base)
base.extend(self)
end
def around_aspect(method_name, before_proc, after_proc)
code = %Q[
def #{method_name} *args, &block
#{before_proc.call}
old_#{method_name} *args, &block
#{after_proc.call}
end
]
class_eval %Q[
alias_method :old_#{method_name}, :#{method_name}
]
class_eval code
end
# def before_aspect method_name, before_proc
# around_aspect method_name, before_proc, ->(){}
# end
#
# def after_aspect method_name, after_proc
# around_aspect method_name, ->(){}, after_proc
# end
end
end
class Test
include Utils::Aspects
def test
puts 'test'
end
before = ->(){puts 'before'}
after = ->(){puts 'after'}
around_aspect :test,before,after
end
Test.new.test
问题在于,当我Test.new.test
时,我希望它能打印出来
之前,测试和之后"为了。但是现在它打印"之前,之后和测试"
答案 0 :(得分:4)
问题在于,当我
Test.new.test
时,我希望它能打印出来 之前,测试和“按顺序。但现在它打印”之前,之后和测试“
不,它没有。致电Test.new.test
时,它只会打印test
。定义包装方法时,即在调用before
时,会打印after
和around_advice
。
尝试在调用puts
和调用around_advice
之间设置Test.new.test
(并尝试多次调用test
)以观察:
puts '______________________'
Test.new.test
Test.new.test
# before
# after
# ______________________
# test
# test
在定义方法时,您只调用lambdas一次:
code = %Q[
def #{method_name} *args, &block
#{before_proc.call}
# ^^^^^^^^^^^^^^^^^^^
old_#{method_name} *args, &block
#{after_proc.call}
# ^^^^^^^^^^^^^^^^^^
end
]
每次调用方法时都需要调用它们:
code = %Q[
def #{method_name} *args, &block
before_proc.call
old_#{method_name} *args, &block
after_proc.call
end
]
然而,使用Module#prepend
会更容易,毕竟,这就是它的用途:
module Aspects
refine Module do
def around_aspect(method_name, before_proc, after_proc)
prepend(Module.new do
define_method(method_name) do |*args, &block|
before_proc.()
super(*args, &block)
after_proc.()
end
end)
end
end
end
class Test
using Aspects
def test
puts 'test'
end
before = -> {puts 'before'}
after = -> {puts 'after'}
around_aspect :test, before, after
end
答案 1 :(得分:0)
把我的代码放在这里。这就是我最终实现我想要做的事情,如上所述,module.prepend是另一种方式
module Utils
module Aspects
def self.included(base)
base.extend(self)
end
def around_aspect(method_name, before_proc, after_proc)
new_method_name = Random.new_seed.to_s
alias_method :"#{new_method_name}", :"#{method_name}"
define_method "#{method_name}" do |*args, &block|
before_proc.call
send(:"#{new_method_name}", *args, &block)
after_proc.call
end
end
def before_aspect method_name, before_proc
around_aspect method_name, before_proc, ->(){}
end
def after_aspect method_name, after_proc
around_aspect method_name, ->(){}, after_proc
end
end
end
class Test
include Utils::Aspects
def test
puts 'test'
end
before = ->(){puts 'before'}
after = ->(){puts 'after'}
before_aspect :test, before
after_aspect :test, after
end
Test.new.test