Why is ActiveResource::Base.site a class variable?

This causes problems in the following scenario:

1. You use ActiveResource to post data to an external site using
subdomains for individual accounts (e.g. Lighthouse)
2. You want your app to allow multiple users to do this (register
their Lighthouse account/URI to automatically push their data from
your app to Lighthouse).

There's no way I can see to support this other than creating a
separate (dynamically named) class for each user/site.

Questions:
* Is there a reason it can't/shouldn't be an instance variable?
* If there is a good reason, are there any workarounds or third-party
alternatives which don't have this limitation (other than directly
handling the HTTP calls)?

Thanks,
-- Chad

This causes problems in the following scenario:

1. You use ActiveResource to post data to an external site using
subdomains for individual accounts (e.g. Lighthouse)
2. You want your app to allow multiple users to do this (register
their Lighthouse account/URI to automatically push their data from
your app to Lighthouse).

There's no way I can see to support this other than creating a
separate (dynamically named) class for each user/site.

The shopify API has this same issue, the solution there is to
dynamically switch out the site in a before_filter / at the start of
every delayed_job worker.

It's not an ideal solution but it's way easier than doing dynamically
named classes.

Questions:
* Is there a reason it can't/shouldn't be an instance variable?

What would the api look like here? I could see something like

* If there is a good reason, are there any workarounds or third-party
alternatives which don't have this limitation (other than directly
handling the HTTP calls)?

Take a look at how the shopify API works, it's been really really
nice to deal with, and while switching out the site in a filter isn't
the coolest-looking solution, it's similar to using multiple database
connections in an AR app.

Questions:
* Is there a reason it can't/shouldn't be an instance variable?

What would the api look like here? I could see something like

Seems I didn't hit paste...

ActiveResource::Base.with_site(...) do
ShopifyAPI::Shop.find(:first)
# etc.
end

Long-term, we want to try to get away from using global state like
this as much as possible, but fixing it can sometimes open a thorny
can of worms. Koz's solution, paired with a mutex or thread-local (for
threadsafe scenarios) is a good workaround for now.

What's the can of worms? Just thread safety?

How about this approach (suggested by Adam Milligan):

class ActiveResource::Base
  def self.connect(current_site)
    old_site = site
    begin
      self.site = current_site
      connection(:refresh)
      yield
    ensure
      self.site = old_site
    end
  end
end

This would also need to be made threadsafe, but isn't it essentially
the same thing Koz suggested, without a dependency on DelayedJob?

-- Chad

How about this approach (suggested by Adam Milligan):

class ActiveResource::Base
def self.connect(current_site)
old_site = site
begin
self.site = current_site
connection(:refresh)
yield
ensure
self.site = old_site
end
end
end

This would also need to be made threadsafe, but isn't it essentially
the same thing Koz suggested, without a dependency on DelayedJob?

This is basically exactly what I was suggesting, apologies for not
being clearer ;).

Any updates on this? Has any progress been made on making
ActiveResource thread-safe (either in Rails 3 or in plugins/forks)?

Thanks,
-- Chad