2017-10-26 16 views
0

私はBasicObjectプロキシを使用しています。実際のオブジェクトまたはそのようなプロキシを渡したかどうかを検出する必要があります。問題は、このようなis_a?classような方法は、これは私がそれを使用しています方法の例ですBasicObjectプロキシを検出するにはどうすればいいですか?

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?をプロキシとして定義するにはどうすればよいですか?

+0

これは、単に観察答えではありません:プロキシを使用しての全体のポイントは、プロキシがスタンドで本物のため何時の間にかとして使用することができるということです。 IOW:プロキシと実際のものを区別することはできません。実際、あなたが求める人に応じて、あるオブジェクトが別のオブジェクトを擬似的にシミュレートする能力は、OOPの中心またはOOP、または*定義*にさえあります。 –

+0

@JörgWMittag問題は私のサービスでは本物のものよりもプロキシがほしいと思っていますが、実際のところはすでにプロキシであるかもしれません。 私はプロキシ以上にプロキシを持つことを避けたいのですが、それ自体問題ではないかもしれません。 –

+0

私はこの質問が詐欺であるかどうかはわかりません。メソッドを 'Object'から再バインドすることも可能ですが、特にプロキシの場合は、独自の実装を提供する方が望ましいかもしれません。 –

答えて

1

問題があります例えばis_a?又は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 
+0

あなたは正しいのです...実際には、私が 'is_a_proxy? 'を定義するよりもおそらく良いでしょう、私は' is_a? 'メソッドを2番目の提案のように保つことができます –

0

実際にRUby 2 hereの回答が見つかりました。私の質問はほとんど重複したような感じが、私の場合、私は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 
関連する問題