/ / Jak wykryć Proxy BasicObject? - ruby, proxy, ruby-2.3

Jak wykryć Proxy BasicObject? - ruby, proxy, ruby-2.3

Używam Proxy BasicObject i muszę wykryć, czy przekazałem rzeczywisty obiekt LUB taki serwer proxy. Problem polega na tym, że metody takie jak is_a? lub class nie są zdefiniowane

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

Oto przykład tego, jak go używam:

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

Poniższe więc nie działa

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

Jak mogę zdefiniować is_a? dla Proxy (lub faktycznie identyfikującego używam proxy)?

Odpowiedzi:

1 dla odpowiedzi № 1

Problem polega na tym, że metody takie jak is_a? lub class nie są zdefiniowane

Oczywistym rozwiązaniem problemu "jakaś metoda nie jest zdefiniowana", jest zdefiniowanie metody:

class ControllerProxy
def class; ControllerProxy end

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

Ale! To pokonuje cały cel proxy, który jest nie do odróżnienia od prawdziwego. Lepszym sposobem byłoby IMO:

class ControllerProxy
def class; Controller end

def is_a?(mod)
Controller < mod
end
end

0 dla odpowiedzi nr 2

Właściwie znalazłem odpowiedź dla RUby 2 tutaj. Moje pytanie prawie wydaje się być duplikatem, ale w moim przypadku mówiłem o rozszerzeniu klasy basicObject, która nie łata samej klasy BasicObject

W takim przypadku zastosowanie to staje się:

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