1

我正在创建一个类来包装 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 和命名空间变量,而不是 @url 和 @namespace 实例变量。

所以似乎在传入块初始化wsdl文档时,局部变量的上下文被保留,而实例变量的上下文则没有。这是 Ruby 的基本行为吗?

4

1 回答 1

1

幸运的是,这不是“Ruby 的基本行为”,而是与 Savon 如何评估传递给Savon::Client.new.

如果您不向该块传递任何参数,Savon 使用带有委托的 instance_eval来评估该块,不幸的是该块不适用于实例变量,但可以访问局部变量以及您的类中的方法。

作为替代方案,您可以将 1 到 3 个参数传递给块,并按以下顺序接收可用的对象:

[wsdl, http, wsse]

在您的情况下,您只需要第一个对象,因此您的代码如下所示:

@client = Savon::Client.new do |wsdl|    # <= one argument
  wsdl.endpoint = @url
  wsdl.namespace = @namespace
end

请查看Savon 的文档以获取更多信息。

于 2011-03-23T14:32:50.220 回答