htm_safe/gsub: html_escape in view, then gsub in partial #3024

Closed
jrochkind opened this Issue Sep 14, 2011 · 4 comments

Projects

None yet

2 participants

@jrochkind

Okay, this is a really weird one. Rails 3.1.0 (may exhibit earlier)

If you call html_escape on a string, and then call gsub on the output in block form, then $1/$2 captures don't get set properly.

test.html.erb

<%= my_helper(  html_escape( "quick brown fox" )) %>

test_helper.rb

module TestHelper
    def my_helper(string)
         string.gsub("b(row)n") do 
              raise "should not be nil" if $1.nil?
              $1.titlecase
          end
     end
end

Appears to raise. Something about calling the output of html_escape helper method messes up gsub in block form. It's not reproducible if you take a string and manually call my_string.html_safe on it, so it doesn't exhibit for any html_safe? string. It seems to reproduce only if you actually call html_escape. Huh?

@jrochkind

Although I realize there's no reason for me to be calling html_escape there anyway in a rails 3.x world, that's just leftover code I migrated from rails 2.x --- ordinarily calling html_escape shouldn't hurt, but in most cases (including mine) it isn't neccesary. And apparently in some edge cases, it triggers bugs? But I guess may not be that important of a bug since most people may not need html_escape, I dunno.

@jrochkind jrochkind closed this Sep 14, 2011
@jrochkind

ah, thanks (and so quick). Will close this as duplicate. I realize I DO need to call gsub on a string I've html_escape'd for my purposes, this is an annoying bug.

One work-around:

string = "#{html_escape(string)}", to get a string that is html-escaped, but is NOT marked html_safe, so you can gsub on it without breaking $1, $2, and then call #html_safe on the output post-gsub if you want.

@dmathieu

You can call html_escape on your string. Your example above should become :

module TestHelper
  def my_helper(string)
    string.to_str.gsub("b(row)n") do 
      raise "should not be nil" if $1.nil?
      $1.titlecase
    end
  end
end

The only change is line 3.
string.gsub("b(row)n") do becomes string.to_str.gsub("b(row)n") do

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment