Diese Präsentation wurde erfolgreich gemeldet.
Wir verwenden Ihre LinkedIn Profilangaben und Informationen zu Ihren Aktivitäten, um Anzeigen zu personalisieren und Ihnen relevantere Inhalte anzuzeigen. Sie können Ihre Anzeigeneinstellungen jederzeit ändern.

gsub with ActiveSupport::SafeBuffer

2.734 Aufrufe

Veröffentlicht am

Railsのhelperでnamed captureを使ったgsubを使ったらハマった話

Veröffentlicht in: Technologie
  • Loggen Sie sich ein, um Kommentare anzuzeigen.

gsub with ActiveSupport::SafeBuffer

  1. 1. Railsのhelperでnamed capture使ったらハマった話 chezou kawasaki.rb #010
  2. 2. 正規表現とnamed capture • 正規表現のグループに名前をつけて、後方参 照できる pat = /(?<good>good|nice|greate) catch/! #=> /(?<good>good|nice|greate) catch/! pat === 'nice catch!!'! #=> true! Regexp.last_match! #=> #<MatchData "nice catch" good:"nice">! Regexp.last_match[:good]! #=> "nice"!
  3. 3. helperでnamed capture • Railsのhelperでnamed capture使ったgsubした ら… module FooHelper! def replace_awesome(str)! str.gsub(pat){|m| "#{m}!!!" if Regexp.last_match[:good]}! end! end! ! - str = 'nice catch'! = replace_awesome(str) #=> "nice catch!!!"! # こういうのがやりたい!
  4. 4. 現実 = replace_awesome(str)! NoMethodError: undefined method `[]' for nil:NilClass ( д) ゚ ゚
  5. 5. なぜだろう? => ActiveSupport::SafeBuffer module FooHelper! def replace_awesome(str)! p(str.class) ! str.gsub(pat){|m| "#{m}!!!" if Regexp.last_match[:good]}! end! end!
  6. 6. AS::SafeBufferとは • RailsのviewではHTMLの特殊文字(<,>,&,")を自 動的にエスケープしてくれる • その時に出力されるクラスがAS::SafeBuffer "".html_safe + "<" #=> "&lt;"! ("".html_safe + "<").class #=> ActiveSupport::SafeBuffer! http://guides.rubyonrails.org/active_support_core_extensions.html#extensions-to-string
  7. 7. SafeBufferのgsubを見た rails/activesupport/lib/active_support/core_ext/string/output_safety.rb module ActiveSupport!   class SafeBuffer < String!     UNSAFE_STRING_METHODS = %w(! capitalize chomp chop delete downcase gsub lstrip next reverse rstrip! slice squeeze strip sub succ swapcase tr tr_s upcase prepend! )! …!     UNSAFE_STRING_METHODS.each do |unsafe_method|!       if unsafe_method.respond_to?(unsafe_method)!         class_eval <<-EOT, __FILE__, __LINE__ + 1! def #{unsafe_method}(*args, &block) # def capitalize(*args, &block)! to_str.#{unsafe_method}(*args, &block) # to_str.capitalize(*args, &block)! end # end! ! def #{unsafe_method}!(*args) # def capitalize!(*args)! @html_safe = false # @html_safe = false! super # super! end # end! EOT!       end!     end!
  8. 8. Rubyのみの再現コード def test(*args, &block)! 'hogehoge'.gsub(/h/, &block)! p Regexp.last_match! end!  ! test do |matched|! p Regexp.last_match! end!
  9. 9. Rubyのみの再現コード def test(*args, &block)! 'hogehoge'.gsub(/h/, &block)! p Regexp.last_match #=> <MatchData "h">! end!  ! test do |matched|! p Regexp.last_match #=> nil! end!
  10. 10. 仕様です
  11. 11. Rubyのみの再現コード def test(*args, &block)! 'hogehoge'.gsub(/h/, &block)! p Regexp.last_match #=> <MatchData "h">! end!  ! test do |matched|! p Regexp.last_match #=> nil! end! block内のscopeと違うので取れません
  12. 12. 回避方法 module FooHelper! def replace_awesome(str)! str.to_str.gsub(pat){|m| "#{m}!!!" if $~[:good]}! end! end!  ! - str = 'nice catch'! = replace_awesome(str) #=> "nice catch!!!"!

×