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...) に関係なくうまく機能しますが、2 回目の呼び出しでは常に失敗します。

なぜこれが起こっているのか、そしてそれを修正するために何ができるのかを理解したいと思います.

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 に答える