I have done this a thousand times but I'm still not comfortable with how the render :json
handles str开发者_JAVA百科ings.
To set a scope let's talk about Rails 3
This is how it behaves right now:
...
render :json => 'This is the string'
...
Will be returning to the browser:
This is the string
That's actually not a valid JSON response :S
Ideally it should be rendering something like this:
"This is the string"
Even the rails guides say:
You don’t need to call to_json on the object that you want to render. If you use the :json option, render will automatically call to_json for you.
And calling "This is the string".to_json
is actually returning "\"This is the string\""
as expected.
"This is the string".to_json #=> "\"This is the string\""
Am I so wrong ?
I agree that this is unexpected behavior at first, but it actually makes some good sense.
Consider, for example, what you would expect this to do:
output = {'foo' => 'bar'}.to_json
render :json => output
Even though the to_json
is kinda redundant, you expect the result to be {foo: "bar"}
. However, note that the result of {'foo' => 'bar'}.to_json
is actually a string. So, the above code block is equivalent to:
render :json => '{foo: "bar"}'
If render
were to JSON-encode strings passed to :json
, you would get "{foo: \"bar\"}"
, which is definitely not expected behavior.
So here's the deal: render
checks to see if the :json
argument is a string. If so, it assumes that it's a JSON string and you already ran to_json
, and passes the string along. If not, it runs to_json
on the object.
I think the documentation should probably clarify that, but there you have it. Though it's not exactly intuitive at first glance, I would be surprised if it worked any other way.
精彩评论