2

我正在使用动态调度在从 ActiveResource 继承的类中定义几个类方法。

class Invoice < ActiveResource::Base
  self.site = 'http://localhost:8080/'

  def self.define(method)
    define_singleton_method(method) do |params = {}|
      site = self.site
      self.site = "#{self.site}/Invoice/#{method.to_s.camelize(:lower)}"

      puts "self.site -> #{self.site}"  
      results = Invoice.all(params: params)

      self.site = site
      puts "changing self.site back to #{site}"     

      return results
    end
  end

  define :get_details
  define :put_approval
  define :get_attachment
  define :get_pending_notifications
end

这适用于第一次通话,无论它是什么(Invoice.get_details、Invoice.get_pending_notifications...),但在第二次通话时总是失败。

我想了解为什么会发生这种情况以及我可以做些什么来解决它。

4

2 回答 2

1

进一步研究这一点,我发现self.site当我要求它时它实际上并没有改变。它告诉我它在日志中发生变化,但它在说谎! self.site在调用的第一个方法中不会从其初始设置状态更改。我有一个关于为什么这不起作用的理论以及让它起作用的解决方法。

首先,我的理论:

当任何一个定义的类方法被调用时,site被设置。由于site超出了被调用的类方法的范围,因此一旦初始设置,之后就无法更改。

一个例子:

Invoice.get_details

Invoice.site最初设置为“localhost:8080/Invoice/getDetails”

Invoice.get_pending_notifications

Invoice.site无法更改,因为它已经定义为“localhost:8080/Invoice/getDetails”

以上只是一个工作理论。

我是如何做到这一点的:

删除self.site除初始集之外的所有引用self.site = "localhost:8080",改为使用 url 字符串。(在 http://ofps.oreilly.com/titles/9780596521424/activeresource_id59243.html的“从自定义路径中查找资源”部分下)

class Invoice < ActiveResource::Base
  self.site = "localhost:8080"
  def self.define(method)
    define_singleton_method(method) do |params = {}|
      url = "#{self.site}/Invoice/#{method.to_s.camelize(:lower)}"

      # results = Invoice.all(params: params) <- Change this call to below
      results = Invoice.find(:all, from: url, params: params) 

      return results
    end
  end

  define :get_details
  define :put_approval
  define :get_attachment
  define :get_pending_notifications
end

使用上面的代码,我可以调用任何定义的方法,每个方法都指向不同的 url,没有问题。

于 2013-05-23T16:49:29.960 回答
0

很可能该站点没有正确重置。试试这个,它在 ruby​​ 控制台下工作:

class Invoice < ActiveResource::Base
  self.site = 'http://localhost:8080/'

  def self.define(method)
    define_singleton_method(method) do |params = {}|
      site = self.site
      begin
        self.site = "#{self.site}/Invoice/#{method.to_s.camelize(:lower)}"
        Invoice.all(params: params)
      ensure
        # this code will always be run, even if there is an exception above
        # and it won't affect the original value returned above
        self.site = site
      end
    end
  end

  define :get_details
  define :put_approval
  define :get_attachment
  define :get_pending_notifications
end
于 2013-05-21T20:17:42.990 回答