新手问题 如何在 Ruby 中实现 before_filter 之类的功能?

qifengle · 2014年07月16日 · 最后由 rei 回复于 2014年07月16日 · 4259 次阅读

如题:如何实现一个 before_filter 功能?刚刚找的一段代码:

module Filter
  def before_filter name
    @@filter = name
  end

  def method_added name
    return if @filtering 
    return if @@filter == name
    return if name == :initialize

    @filtering = true

    alias_method :"original_#{name}", name
    define_method name do |*args|
      self.send @@filter
      self.send :"original_#{name}", *args
    end
    @filtering = false
  end
end

class Test
  extend Filter

  before_filter :logger

  def foo
    puts "call #{__method__}"
  end 

  private
    def logger
      puts "logging..."
    end
end

Ruby 版本无限定,可以使用最新的 2.x, 希望大家分享下您的方法?

before_filter 在 Rails 中是由 ActiveSupport 的 Callback 实现的吧,其实那个没任何技术含量的。。。

#1 楼 @iBachue 是怎么实现的?说说其原理呗?

#1 楼 @iBachue 我意思是说自己实现类似功能,非 rails 代码,不依赖其他 gem

可以使用 继承 或者 ActiveSupport 的 Callback 实现

#4 楼 @chucai 你是说这个?其实我意思是说如何写自己的 ActiveSupport::Callbacks,因为只是 ruby 代码中用用。

class Record
  include ActiveSupport::Callbacks
  define_callbacks :save

  def save
    run_callbacks :save do
      puts "- save"
    end
  end
end

class PersonRecord < Record
  set_callback :save, :before, :saving_message
  def saving_message
    puts "saving..."
  end

  set_callback :save, :after do |object|
    puts "saved"
  end
end

person = PersonRecord.new
person.save

这些 filter 原理其实都很简单,用一个 instance variable 或 class variable,设为空 array, 定义一个 DSL 以 symbol 格式推入 method name,用的时候遍历 array, 一个个 send。稍难一点的地方在于判断是否需要线程安全。因为 class variable 最简单,但不是线程安全的。

8 楼 已删除
需要 登录 后方可回复, 如果你还没有账号请 注册新账号