Turns out the connection between ActiveResource models is shared. So if you set the format in one model, it does stay different from the format in other models. However, if you call the .connection.format
method on two separate models, that format changes every time you set a new format. So if Profile
got loaded in second with the format :json
then .connection.format
for both models turns into ActiveResource::Formats::JsonFormat
My original question was completely different (I didn't fully understand what was going on) - you can look at the edit history to see the original version. Hopefully I'll get more responses...
Proof:
class Location < ActiveResource::Base
self.format = :xml
end
class Profile < ActiveResource::Base
self.format = :json
end
Then in a rails console
...
>> Location.format
=> ActiveResource::Formats::XmlFormat
>> Location.connection.format
=> ActiveResource::Formats::XmlFormat
So far so good... the Location
model and it's connection have the correct format.
>> Profile.format
=> ActiveResource::Formats::JsonFormat
Looks normal, that's the format for Profile
that I want.
>> Location.format
=> ActiveResource::Formats::XmlFormat
Ok... Location.format is still the same after having loaded the Profile model Note: These models are lazy-loaded so their files and code aren't included until you attempt to call the class name.
>> Location.connection.format
=> ActiveResource::Formats::JsonFormat
And here the problem begins. After we've made a call to the Profile model, it f'ed up the Location.connection.format
>> Profile.connection.format
=> ActiveResource::Formats::JsonFormat
The formats are not supposed to be the same. This causes parsing to be completely broken when you make a call to something like Location.find(:all, :from => "/something.xml") - it attempts to parse the xml
as json
I guess my question now is - how do I separate the two connections? (Or otherwise resolve this issue)
Edit to add this test in the console:
>> Location.connection == Profile.connection
=> true
This... feels like a bug.
I was looking at ActiveResource
source code. When you call the format=
method in your ARes class it writes the format to connection.format
.
The connection
method in this context will grab @@connection
if it's defined, otherwise it will call superclass.connection
. In our case superclass
is ActiveResource::Base
. As you can guess, @@connection
on the Location
or Profile
models is not defined. It will get set if you call self.site=
on your class, in which case the self.format=
method will set the format on your class-specific version of the connection
object.
In my case I have no reason to use a different site variable for the different ActiveResource models, just a different return format. For this reason I was setting ActiveResource::Base.site = "myresource.local"
in development (and the appropriate one in the production.rb env file too).
So my fix for this problem?
class Location < ActiveResource::Base
self.site = self.site
self.format = :xml
end
Yep, self.site = self.site
forces the class to use it's own connection object. Somehow I feel like self.format =
should also...
Not gonna accept this answer quite yet because it feels like a hack and/or bug, but that's how I solved it for now and it appears to work.
Hopefully someone else has thoughts on this? It doesn't seem like very many people use ActiveResource but we use it on a daily basis and I have run into this before.