Ответ 1
Я согласен, что сначала это неожиданное поведение, но на самом деле это имеет смысл.
Рассмотрим, например, то, что вы ожидаете от этого:
output = {'foo' => 'bar'}.to_json
render :json => output
Несмотря на то, что to_json
является излишним, вы ожидаете, что результатом будет {foo: "bar"}
. Однако обратите внимание, что результат {'foo' => 'bar'}.to_json
на самом деле является строкой. Таким образом, вышеуказанный блок кода эквивалентен:
render :json => '{foo: "bar"}'
Если render
были для строк JSON-encode, переданных в :json
, вы получили бы "{foo: \"bar\"}"
, что явно не ожидалось.
Итак, здесь сделка: render
проверяет, является ли аргумент :json
строкой. Если это так, предполагается, что это строка JSON, и вы уже запустили to_json
и передаете строку. Если нет, он запускает to_json
объекта.
Я думаю, что документация должна, вероятно, прояснить это, но там у вас это есть. Хотя на первый взгляд это не совсем интуитивно, я был бы удивлен, если бы он работал каким-либо другим способом.