Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does ruby's to_json break embedded javascript?

Problem

In PHP I'd do this

<html>
<body>
    <script>
        <?php
        $templates = array(
          'result' => file_get_contents('template.html')
          );
          echo '__templates = ' . json_encode($templates) . ';';
          ?>
    </script>
</body>
</html>

So I did this in Sinatra

<!DOCTYPE html>
<html>
<body>
    <script type="text/javascript">
        __templates = <%= get_templates  %>;
    </script>
</body>
</html>

And my Sinatra routes file looks like this:

require 'sinatra'
require 'json'
require 'erb'

helpers do
    def get_templates
        {'result' => (erb :template2)}.to_json
    end
end

get '/' do
    erb :index
end

But my javascript object ends up broken when I consume the __templates object from jquery.

What does ruby's to_json do that PHP's does not?

php result

{"result":"<!doctype html>\n<html>\n\n<head>\n\t<meta charset=\"UTF-8\">\n\t<title>{{ TITLE }}<\/title>\n\n\t<style type=\"text\/css\">\n\t{{ CSS }}\n\t<\/style>\n<\/head>\n\n<body>\n\n\t{{{ HTML }}}\n\n\t<script src=\"{{{ JSLIB }}}\"><\/script>\n\t<script src=\"{{{ PREFIX }}}\"><\/script>\n\t<script>\n\t\tfunction __run() {\n\t\t\t{{{ JS }}}\n\t\t}\n\t<\/script>\n\n<\/body>\n\n<\/html>"}

ruby result

{"result":"<!doctype html>\n<html>\n\n<head>\n    <meta charset=\"UTF-8\">\n    <title>{{ TITLE }}</title>\n\n    <style type=\"text/css\">\n        {{ CSS}}\n    </style>\n</head>\n\n<body>\n\n    {{{ HTML }}}\n\n    <script src=\"{{{ JSLIB }}}\"></script>\n    <script src=\"{{{ PREFIX }}}\"></script>\n    <script>\n        function __run() {\n            {{{ JS }}}\n        }\n    </script>\n\n</body>\n\n</html>\n"};

notice the <\/body> on the php version.

Solution (for now)

I found a solution based on comments posted below. However, I'm not sure if this is the 'one true way', if that exists. NOTE: I'd like to know if this implementation would break something else down the road. I'll be depending on this function throughout my application.

I ended up just using gsub to solve my problem. I wrapped it in a helper like this

helpers do
    def close embedded_json
        embedded_json.gsub('</', '<\/')
    end
    ...
end

and called it like this

__templates = <%= close get_templates  %>;

it seems jangy, but under the covers, maybe the helpers alluded to in rails do the same thing? I'm going to move on for now, but I'd still like to know if I'll be shot in the foot later by this.

like image 790
timsabat Avatar asked Apr 12 '26 01:04

timsabat


1 Answers

It's all about those backslashes.

Anywhere something like </title> shows up in the JSON, it needs to actually be <\/title>

The problem is the .to_json isn't adding those backslashes.

How can we make it?

like image 79
Chris Coyier Avatar answered Apr 13 '26 15:04

Chris Coyier



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!