0

我正在使用 BasicObject 代理,我需要检测我是否通过了实际对象或这样的代理。问题是诸如is_a?or之类的方法class没有定义

module ControllerProxyable
  extend ActiveSupport::Concern

  included do
    attr_reader :controller
    delegate :current_user, to: :controller
  end

  def controller_proxy(controller)
    # is_a? actually is NOT defined for a BasicObject causes the following to crash
    @controller = if controller.is_a?(ControllerProxy) 
      controller
    else
      ControllerProxy.new(controller)
    end
  end
end

class ControllerProxy < BasicObject
  def initialize(controller = nil)
    @controller = controller
  end

  def some_proxy_method
  end

  # def respond_to and respond_to_missing not relevant here
end

这是我如何使用它的一个例子:

class Foo
  include ControllerProxyable

  def initialize(controller: nil)
    controller_proxy(controller)
  end

  def bar
    bar ||= Bar.new(controller: controller)
  end
end

class Bar
  include ControllerProxyable

  def initialize(controller: nil)
    controller_proxy(controller)
  end
end

因此以下内容不起作用

Foo.new(controller: nil).bar.some_proxy_method

如何is_a?为代理定义(或实际识别我正在使用代理)?

4

2 回答 2

1

问题是诸如is_a?or之类的方法class没有定义

“某些方法未定义”问题的明显解决方案是定义方法:

class ControllerProxy
  def class; ControllerProxy end

  def is_a?(mod)
    self.class < mod
  end
end

但!这违背了代理的全部目的,即与真实事物无法区分。更好的方法是 IMO:

class ControllerProxy
  def class; Controller end

  def is_a?(mod)
    Controller < mod
  end
end
于 2017-10-26T10:09:36.057 回答
0

我实际上在这里找到了 RUby 2 的答案。我的问题几乎感觉像是重复的,但在我的情况下,我谈论的是 basicObject 类的扩展,而不是修补 BasicObject 类本身

对于这样的用例,这变为:

def controller_proxy(controller)
    # Note that is_a? is not defined for a proxy
    @controller = if Kernel.instance_method(:class).bind(controller).call <= ServiceControllerProxy
      controller
    else
      ServiceControllerProxy.new(controller)
    end
  end
于 2017-10-26T10:02:57.603 回答