我正在创建一个包装Savon SOAP连接的类,如下所示:
class SOAPConnection
attr_reader :url, :namespace
def initialize(url, namespace)
@url = url
@namespace = namespace
@client = Savon::Client.new do
wsdl.endpoint = @url
wsdl.namespace = @namespace
end
end
end
此代码不起作用。初始化的wsdl文档有一个nil端点和一个nil命名空间。
为了使代码有效,我必须使用以下内容:
class SOAPConnection
attr_reader :url, :namespace
def initialize(url, namespace)
@url = url
@namespace = namespace
@client = Savon::Client.new do
wsdl.endpoint = url # <=== use local variable
wsdl.namespace = namespace # <=== use local variable
end
end
end
请注意,在设置wsdl.endpoint和wsdl.namespace时,我使用的是本地url和namespace变量,而不是@url和@namespace实例变量。
因此,当传入块来初始化wsdl文档时,似乎保留了局部变量的上下文,而实例变量的上下文则没有。这是Ruby的基本行为吗?
答案 0 :(得分:1)
幸运的是,这不是“Ruby的基本行为”,而是与Savon如何评估传递给Savon::Client.new
的块有关。
如果你没有向块传递任何参数,Savon使用instance_eval with delegation来评估不幸与实例变量无关的块,但可以访问本地变量以及类中的方法。
作为替代方案,您可以在块中传递1到3个参数,并按以下顺序接收可用的对象:
[wsdl, http, wsse]
在您的情况下,您只需要第一个对象,因此您的代码将如下所示:
@client = Savon::Client.new do |wsdl| # <= one argument
wsdl.endpoint = @url
wsdl.namespace = @namespace
end
请查看documentation for Savon了解详情。