My to_json call sometimes seems to include some extra cruft that I'm not expecting:
{"response":
[{"attributes":
{
(...actual list of key:value pairs, as expected)
},
"json_class":"Survey",
"attributes_cache":{}
},
{"changed_attributes":{"survey_source":""},
"attributes":
{
(...actual list of key:value pairs, as expected)
},
"json_class":"Survey",
"attributes_cache":{}}
],
"status_code":"200","status_description":"OK"}
What I'm expecting is closer to this:
{"response":
[survey: {
(...list of key:value pairs...)
},
survey: {
(...list of key:value pairs...)
}
],
"status_code":"200","status_description":"OK"}
As far as I can tell, the extra stuff that shows up is used by AR to keep track of the state of dirty objects, but I'm not sure why it gets picked up by to_json. My code does nothing fancy as far as I can tell:
RESPONSE_OK = {"status_code" => "200", "status_description" => "OK"}
@surveys = Survey.find_all_by_state("RUNNING")
response = RESPONSE_OK.merge({"response" => @surveys})
respond_to do |format|
format.json {
render :json => response.to_json(:methods => :intercept, :include => {:question_groups => {:include => [:questions]}})
}
end
I cannot reproduce it on the Rails console (including a simpler example for legibility, but I get the same result for my actual code):
?> s = Survey.find_by_id(49)
=> #<Survey id: 49, name: "Cat?", description: "", created_at: "2010-08-29 17:50:45", updated_at: "2010-08-29 17:50:45", order: nil, entrance_logic: nil, user_id: 187, state: "RUNNING", maxresponses: 0, isrepeatable: false, reward_description: nil, compensation_amount: 0, survey_source: nil, responses_received: nil, is_profile_survey: false, hash_id: "123", survey_alias: "456", prerequisites: nil, is_web_survey: false, max_invites: 0, is_social: true>
>> s.to_json
=> "{"survey":{"survey_source":null,"prerequisites":null,"name":"Cat?","isrepeatable":false,"maxresponses":0,"hash_id":"123","entrance_logic":null,"created_at":"2010-08-29T17:50:45Z","survey_alias":"456","updated_at":"2010-08-29T17:50:45Z","reward_description":null,"responses_received":null,"order":null,"id":49,"user_id":187,"max_invites":0,"is_web_survey":false,"is_social":true,"is_profile_survey":false,"description":"","compensation_amount":0,"state":"RUNNING"}}"
>> s.reward_description = "100 points"
=> "100 points"
>> s.to_json
=> "{"survey":{"survey_source":null,"prerequisites":null,"name":"Cat?","isrepeatable":false,"maxresponses":0,"hash_id":"123","entrance_logic":null,"created_at":"2010-08-29T17:50:45Z","survey_alias":"456","updated_at":"2010-08-29T17:50:45Z","reward_description":"100 points","responses_received":null,"order":null,"id":49,"user_id":187,"max_invites":0,"is_web_survey":false,"is_social":true,"is_profile_survey":false,"description":"","compensation_amount":0,"state":"RUNNING"}}"
>> s.changed
=> ["reward_description"]
>> s.changed_attributes
NoMethodError: Attempt to call private method
from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/attribute_methods.rb:236:in `method_missing'
from (irb):45
from :0
>>
Thanks for any insights! I'm sure I can modify my code to find a workaround (if all else fails I can just build the hash I pass to to_json by hand), but I would like to gain some understanding of why this happens, if possible.