Why does Rails to_json sometimes include attributes, attributes_cache, changed_attributes, etc?
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, :inclu开发者_如何学Gode => {: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.
I just had the same problem - and solved it after extensive googling.
You have a JSON gem installed (perhaps as a dependency of another gem) and this is determining your to_json output.
Remove the gem (if you can) and it'll come good.
:)
精彩评论