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 № 1Problem polega na tym, że metody takie jak
is_a?
lubclass
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