Bre*_*chi 7 ruby model metaprogramming
这是我的实现,以开发方式在模型中的所有方法之前运行代码
调用"before_hook:months_used"方法需要在类的底部到ExecutionHooks才能获得在模块中加载的instance_method.我想在顶部加载实例方法
class BalanceChart < BalanceFind
include ExecutionHooks
attr_reader :options
def initialize(options = {})
@options = options
@begin_at = @options[:begin_at]
end
def months_used
range.map{|date| I18n.l date, format: :month_year}.uniq!
end
before_hook :months_used
end
module ExecutionHooks
def self.included(base)
base.send :extend, ClassMethods
end
module ClassMethods
def before
@hooks.each do |name|
m = instance_method(name)
define_method(name) do |*args, &block|
return if @begin_at.blank? ## the code you can execute before methods
m.bind(self).(*args, &block) ## your old code in the method of the class
end
end
end
def before_hook(*method_name)
@hooks = method_name
before
end
def hooks
@hooks ||= []
end
end
end
Run Code Online (Sandbox Code Playgroud)
你可以这样做prepend.prepend就像include它向类的祖先添加一个模块,但不是在类之后添加它,而是在之前添加它.
这意味着如果在前置模块和类中都存在方法,则首先调用模块实现(super如果它想调用基类,则可以选择调用).
这允许你编写一个钩子模块,如下所示:
module Hooks
def before(*method_names)
to_prepend = Module.new do
method_names.each do |name|
define_method(name) do |*args, &block|
puts "before #{name}"
super(*args,&block)
end
end
end
prepend to_prepend
end
end
class Example
extend Hooks
before :foo, :bar
def foo
puts "in foo"
end
def bar
puts "in bar"
end
end
Run Code Online (Sandbox Code Playgroud)
在实际使用中,您可能希望将该模块存储在某处,以便每次调用before都不会创建新模块,但这只是一个实现细节
| 归档时间: |
|
| 查看次数: |
2960 次 |
| 最近记录: |