I have no trouble making typical AJAX calls to and from Rails(3) with JSON objects and jQuery-rails (jQuery library plus a special rails.js file).
In one controller, though, I want to RETURN some JSON in an erb template (create.js.erb) after an AJAX call.
I've tried every combination of things in the controller (@object.to_json, '[{"content":"hello world"}]', etc.) and in the template itself (JSON.parse(), single quotes, double quotes, etc.), but the object keeps on rendering like this:
'[{"groups":{},"created_at":"2010-09-21T03:49:34Z" ...
and as a result, my jQuery code cannot parse it and I get errors.
How do I need to prep my object in the controller, and what erb syntax do I need in the view for it to render as a valid JSON object?
Thanks so much!
I'm not sure this is the cause, but you can also try playing around with html_safe
method. ERB might be escaping your JSON because it thinks it's not html safe. Try calling that method when using the string:
@object.to_json.html_safe
Using html_escape
or raw
alone will leave you vulnerable to XSS.
Instead, define a sensible version of the json_escape
(a.k.a. j
) helper:
module ActionView::Base
def json_escape(s)
result = s.to_s.gsub('/', '\/')
s.html_safe? ? result.html_safe : result
end
alias j json_escape
end
Use it like this:
<script>
var Accounts = new Backbone.Collection;
Accounts.reset(<%=j @accounts.to_json.html_safe %>);
var Projects = new Backbone.Collection;
Projects.reset(<%=j @projects.to_json(:collaborators => true).html_safe %>);
</script>
See this post for further details.
Be aware that there's a naming conflict between j
aliased to json_escape
in ERB::Util and j
aliased to escape_javascript
in ActionView::Helpers::JavaScriptHelper. It's my hope that the JavaScriptHelper alias will be renamed to js
.
To return json
you have to write your render in the controller as follows:
render :json => @object
and the .to_json
will automatically be called.
If you would want to include some relations, you could do the following:
render :json => @post.to_json(:include => [:comments, :authors])
I am not sure if it would work to use an erb to render your json.
You can call render in your controller, but that will be a problem if you need to possibly render more than a few partials for subsequent dom insertion by the handler. I needed to set multiple html fragments into a hash, and I've been able to return erb which basically uses hash.to_json.html_safe as neutrino suggests above and allows me to render multiple partials in the process.
Only to_json.html_safe
is needed:
> `'<script>'.to_json`
=> "\"\\u003cscript\\u003e\""
Patch to make to_json
respond to html_safe?
and return true
automatically:
# just use .to_json instead of .to_json.html_safe
ActiveSupport::JSON.class_eval do
class << self
def encode_with_html_safe *args
self.encode_without_html_safe(*args).html_safe
end
alias_method_chain :encode, :html_safe
end
end