ruby - 在 ruby​​ 模型中调用方法之前

标签 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

最佳答案

您可以使用 prepend 执行此操作. prepend 类似于 include,因为它向类的祖先添加了一个模块,但是它不是在类之后添加它,而是在类之前添加它。

这意味着如果一个方法同时存在于前置模块和类中,那么首先调用模块实现(如果它想调用基类,它可以选择调用 super)。

这允许你像这样写一个钩子(Hook)模块:

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

在实际使用中,您可能希望将该模块存储在某处,以便每次调用 before 时都不会创建新模块,但这只是一个实现细节

关于ruby - 在 ruby​​ 模型中调用方法之前,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29785454/

相关文章:

ruby - 如何隐藏或删除 gem 1.8.x 中的弃用通知?

ruby - 使用 Nokogiri 读取 XML 文件是否需要根元素?

java - Wicket - 在单击事件上使用可加载可拆卸模型初始化组件

ios - MVVM 在 iOS 中的使用

julia - 在 Julia 中迭代具有不同数量参数的不同函数

windows - 手动安装 Ruby 1.8.7(和其他东西)

ruby - Ruby 中的 RDF 现状

c# - 正确方法: Mapping ViewModel and DataModel

确定类型是否可调用的 C++ 元函数

python - 使用装饰器管理函数内部的属性