Friday, May 6, 2011

Rails escaping quotation mark in link_to_function partial

I have a little piece of rails code which lets users enter a review. If one already is written it displays the current review with a link to edit it.

      <div id="text_area">
        <% if @user_rating.review.blank? %>
          <%= render :partial => "reviews/text_area" %>
        <% else %>
          <%= simple_format @user_rating.review %>
          <%= link_to_function "Edit Review" do |page|
            page.replace_html :text_area, :partial => "reviews/text_area"
          end %>
        <% end %>
      </div>

This works correctly EXCEPT if the review contains a double quote character. Here is the HTML output it generates after a user has already written a review (the else block from above).

      <div id="text_area">
          <p>some text with "quotation marks"</p>
          <a href="#" onclick="try {
Element.update(&quot;text_area&quot;, &quot;&lt;form action=\&quot;/pages/iphone-reviews/reviews/new/write\&quot; class=\&quot;edit_rating\&quot; id=\&quot;edit_rating_16\&quot; method=\&quot;post\&quot;&gt;&lt;div style=\&quot;margin:0;padding:0\&quot;&gt;&lt;input name=\&quot;_method\&quot; type=\&quot;hidden\&quot; value=\&quot;put\&quot; /&gt;&lt;input name=\&quot;authenticity_token\&quot; type=\&quot;hidden\&quot; value=\&quot;fSZK30kpWEUtCxOvr4xDF1O+puDiPm87mhaxaLirIT8=\&quot; /&gt;&lt;/div&gt;\n        &lt;textarea cols=\&quot;40\&quot; id=\&quot;rating_review\&quot; name=\&quot;rating[review]\&quot; rows=\&quot;20\&quot; style=\&quot;width:100%;height:150px;\&quot;&gt;some text with &quot;quotation marks&quot;&lt;/textarea&gt;\n&lt;/form&gt;&quot;);
} catch (e) { alert('RJS error:\n\n' + e.toString()); alert('Element.update(\&quot;text_area\&quot;, \&quot;&lt;form action=\\\&quot;/pages/iphone-reviews/reviews/new/write\\\&quot; class=\\\&quot;edit_rating\\\&quot; id=\\\&quot;edit_rating_16\\\&quot; method=\\\&quot;post\\\&quot;&gt;&lt;div style=\\\&quot;margin:0;padding:0\\\&quot;&gt;&lt;input name=\\\&quot;_method\\\&quot; type=\\\&quot;hidden\\\&quot; value=\\\&quot;put\\\&quot; /&gt;&lt;input name=\\\&quot;authenticity_token\\\&quot; type=\\\&quot;hidden\\\&quot; value=\\\&quot;fSZK30kpWEUtCxOvr4xDF1O+puDiPm87mhaxaLirIT8=\\\&quot; /&gt;&lt;/div&gt;\\n        &lt;textarea cols=\\\&quot;40\\\&quot; id=\\\&quot;rating_review\\\&quot; name=\\\&quot;rating[review]\\\&quot; rows=\\\&quot;20\\\&quot; style=\\\&quot;width:100%;height:150px;\\\&quot;&gt;some text with &quot;quotation marks&quot;&lt;/textarea&gt;\\n&lt;/form&gt;\&quot;);'); throw e }; return false;">Edit Review</a>

      </div>

This example breaks because the text of the review contains a double quote. It works with single quotes and any other text I can think of. I think rails is not escaping the double quote correctly in the javascript.

The error which comes up in Firebug is this:

missing ) after argument list [Break on this error] \" id=\"rating_review\" name=\"rating[re...n:right;\">\n

I'm at a loss on how to fix this one. Thanks!

From stackoverflow
  • You could write a javascript escape helper:

    def escape_javascript(javascript)
            javascript.gsub!("\r\n", "\\n")
            javascript.gsub!(/\n|\r/, "\\n")
            javascript.gsub(/["']/) {|m| "\\#{m}"} || javascript
    end
    

    and call it when you save your review.

    Brian Armstrong : this would save it to the database in an escaped format right? seems less than ideal, since it would require unescaping it any time it was displayed in the view, right?
    MickTaiwan : unescaping would not be necessary if you escape it in HTML like escaping " into " or \r\n into
    . See http://www.theukwebdesigncompany.com/articles/entity-escape-characters.php
    Brian Armstrong : I think unescaping would not be necessary to display the html on a page, but if they go back to edit the text they wrote, they will want to edit the exact text they wrote. Found a solution below that worked...but thanks for the response, I appreciate it!
  • Found a solution which worked. I'm not really sure why it worked but it did.

    A couple times up above I call a partial to render the text area and form where the user can edit their review, like this

    <%= render :partial => "reviews/text_area" %>
    

    All I had to do was go in and edit this partial. One of lines in the form looked like this:

    <%= f.text_area :review %>
    

    All I did was change it to this:

    <textarea cols="40" id="rating_review" name="rating[review]" rows="20"><%=@user_rating.review%></textarea>
    

    Basically just put it in manually so it didn't use the rails function to generate the text area. For whatever reason, it works now. May be something that could be improved in the rails text_area function.

0 comments:

Post a Comment