I want to be able to set class attributes (in particular,
ActiveResource::Base user, password, site, etc.) and for them to be
isolated to a given request, both in terms of thread safety, and so
that for the next request they are reset to defaults. For instance, if
I set user and password, I want to make sure the user and password set
for one user do not accidentally get used for a different user on a
subsequent request. I could do this with a before_filter, but that
seems like the wrong place to manage a model class' instance
variables.
I'm not sure if the threading issue is really a problem, because I
understand most rails servers are single threaded, but would it be a
good idea to use Thread.current in class_attribute to provide thread
safety?
Secondly, what do you think of providing a way of resetting the value
of class attributes between requests?
Perhaps:
class_attribute :x, :default => 'x will have this value at the
beginning of every request'
or
class_attribute :x
class_initializer :set_x
def self.set_x
# this gets run at the beginning of every request
self.x = 'Initial value'
end
ActiveResource::Base.user doesn't actually seem to be using
class_attribute right now, but I assume it could be updated to do so.
Please correct me if I have misunderstood the issues.
My concern is that I don't want one thread to change the user and
password, and suddenly another thread has the wrong credentials set.
Is that a non-issue?
Any comment on resetting the value at the beginning of a request?
My concern is that I don’t want one thread to change the user and
password, and suddenly another thread has the wrong credentials set.
Is that a non-issue?
It’s a real issue, using class_attribute is not suitable for things which are changed by multiple threads.
Any comment on resetting the value at the beginning of a request?
To me it seems that this is only needed because the particular value you’re changing shouldn’t be a class_attribute. Class attributes are great simple solution for things like “what’s the asset path” or “where is the temp directory”, but they’re really just glorified global variables. If you’re flipping them every request then I’d suggest we should fix the particular value to be something thread local or to have a completely different API rather than try to put a band-aid on the whole notion of class attributes.
The possibility that class attributes are the wrong solution had occurred to me, but that is the way things are currently done in ActiveResource.
A possible API change which avoids having to pass the values to every AR call (pretty awkward) would be to instantiate an object which holds the configuration data:
@configured_resource = Resource.configure do |r|
r.user = ‘user’
r.password = ‘pass’
end
@configured_resource.find(1) # passes user and password
That seems like a better design, even though it wouldn’t match the ActiveRecord syntax.
A shortcoming of this solution is that you’d have to perform the configuration for all active resource classes that you’re using, which would significantly reduce its ‘dryness’. Given the current ARes design, having an inheritable configuration is very valuable. Perhaps a better solution would be to create a threadsafe, resettable class-attribute-like structure which could be mixed into ActiveResource::Base?
The current design is, basically, just not really intended for the use case you have in mind. So there are two options, either completely rework ActiveResource’s api such that it does work in this way, or accept its limitations and use one of the dozens of other http client libraries.
I’ve had several clients who use ActiveResource as a nice simple integration API to tie one app to another, but others who had a more complicated authentication or connection management requirement. Those clients use other libraries and I don’t think there’s anything horribly wrong with that.