Railsのhelperでnamed
capture使ったらハマった話
chezou
kawasaki.rb #010
正規表現とnamed capture
• 正規表現のグループに名前をつけて、後方参
照できる
pat = /(?<good>good|nice|greate) catch/!
#=> /(?<good>good|nice|greate) cat...
helperでnamed capture
• Railsのhelperでnamed capture使ったgsubした
ら…
module FooHelper!
def replace_awesome(str)!
str.gsub(pat){|m...
現実
= replace_awesome(str)!
NoMethodError: undefined method `[]' for nil:NilClass
( д) ゚ ゚
なぜだろう?
=> ActiveSupport::SafeBuffer
module FooHelper!
def replace_awesome(str)!
p(str.class) !
str.gsub(pat){|m| "#{m}!!!"...
AS::SafeBufferとは
• RailsのviewではHTMLの特殊文字(<,>,&,")を自
動的にエスケープしてくれる
• その時に出力されるクラスがAS::SafeBuffer
"".html_safe + "<" #=> "&l...
SafeBufferのgsubを見た
rails/activesupport/lib/active_support/core_ext/string/output_safety.rb
module ActiveSupport!
  class S...
Rubyのみの再現コード
def test(*args, &block)!
'hogehoge'.gsub(/h/, &block)!
p Regexp.last_match!
end!
 !
test do |matched|!
p Rege...
Rubyのみの再現コード
def test(*args, &block)!
'hogehoge'.gsub(/h/, &block)!
p Regexp.last_match #=> <MatchData "h">!
end!
 !
test ...
仕様です
Rubyのみの再現コード
def test(*args, &block)!
'hogehoge'.gsub(/h/, &block)!
p Regexp.last_match #=> <MatchData "h">!
end!
 !
test ...
回避方法
module FooHelper!
def replace_awesome(str)!
str.to_str.gsub(pat){|m| "#{m}!!!" if $~[:good]}!
end!
end!
 !
- str = 'n...
of 12

gsub with ActiveSupport::SafeBuffer

Railsのhelperでnamed captureを使ったgsubを使ったらハマった話
Published on: Mar 3, 2016
Published in: Technology      
Source: www.slideshare.net


Transcripts - gsub with ActiveSupport::SafeBuffer

  • 1. Railsのhelperでnamed capture使ったらハマった話 chezou kawasaki.rb #010
  • 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. 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. 現実 = replace_awesome(str)! NoMethodError: undefined method `[]' for nil:NilClass ( д) ゚ ゚
  • 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. 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. 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. Rubyのみの再現コード def test(*args, &block)! 'hogehoge'.gsub(/h/, &block)! p Regexp.last_match! end!  ! test do |matched|! p Regexp.last_match! end!
  • 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. 仕様です
  • 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. 回避方法 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!!!"!

Related Documents