Savon/Ruby 问题:初始化客户端 WSDL 时块中的变量上下文

发布于 2024-10-25 07:05:16 字数 897 浏览 3 评论 0原文

我正在创建一个类来包装 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 的基本行为吗?

I am creating a class to wrap around a Savon SOAP connection, as follows:

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

This code does not work. The wsdl document that gets initialized has a nil endpoint and a nil namespace.

To make the code work, I have to use the following:

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

Note that when setting up the wsdl.endpoint and wsdl.namespace I am using the local url and namespace variables, not the @url and @namespace instance variables.

So it seems that when passing in the block to initialize the wsdl document, the context of local variables is preserved while the context of instance variables is not. Is this a fundamental behaviour of Ruby?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

橙味迷妹 2024-11-01 07:05:16

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

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

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

[wsdl, http, wsse]

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

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

请看一下有关详细信息,请访问 Savon 文档

Luckily this is not "a fundamental behaviour of Ruby", but related to how Savon evaluates the block passed to Savon::Client.new.

If you don't pass any arguments to the block, Savon uses instance_eval with delegation to evaluate the block which unfortunately doesn't work with instance variables, but can access local variables and also methods from your class.

As an alternative, you can pass between 1 and 3 arguments to the block and receive the objects available to you in the following order:

[wsdl, http, wsse]

In your case, you would only need the first object, so your code would look like:

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

Please take a look at the documentation for Savon for more information.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文