Techioz Blog

BasicObject プロキシを検出するにはどうすればよいですか?

概要

BasicObject プロキシを使用していますが、実際のオブジェクトまたはそのようなプロキシを渡したかどうかを検出する必要があります。問題は is_a などのメソッドですか?またはクラスが定義されていません

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 を定義するにはどうすればよいですか?プロキシの場合(または実際にプロキシを使用していることを確認する場合)?

解決策

「一部のメソッドが定義されていない」という問題に対する明らかな解決策は、メソッドを定義することです。

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