I am using dynamic dispatch to define several class methods in a class that inherits from 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
This works great for the first call, whatever it is (Invoice.get_details, Invoice.get_pending_notifications...), but always fails on the second call.
I would like to understand why this is happening and what I can do to get it fixed.
Researching this further, I have found that self.site
is not actually changing when I ask it to. It tells me it is changing in the logs, but it lies! self.site
does not change from its initial set state in the first method called. I have a theory as to why this is not working and a workaround to get it working.
First, my theory:
When any one of the class methods defined is called, site
is set. Since site
is outside of the scope of the class method being called, once it is set initially, it cannot be changed thereafter.
An example:
Invoice.get_details
Invoice.site
is initially set to "localhost:8080/Invoice/getDetails"
Invoice.get_pending_notifications
Invoice.site
cannot be changed because it is already defined as "localhost:8080/Invoice/getDetails"
The above is just a working theory.
How I got this working:
Remove all references to self.site
except for the initial set self.site = "localhost:8080"
and instead use a url string. (Under the section "Finding resources from custom paths" at 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
Using the code above, I can call any of the methods defined, each pointing to a different url, without issue.