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