Railsのシンボル拡張

RailsActionController::Filters::Filter内に以下のメソッドがあります。

def included_in_action?(controller, options)
  if options[:only]
    Array(options[:only]).map(&:to_s).include?(controller.action_name)
  elsif options[:except]
    !Array(options[:except]).map(&:to_s).include?(controller.action_name)
  else
    true
  end
end

んで気になったのが、map(&:to_s)。調べてみるとSymbolクラスを拡張してるみたい。

activesupport-2.1.0/lib/active_support/core_ext/symbol.rb

unless :to_proc.respond_to?(:to_proc)
  class Symbol
    def to_proc
      Proc.new { |*args| args.shift.__send__(self, *args) }
    end
  end
end

なるほど。&がつくとProcオブジェクトが期待されてto_procメソッドがかけられるので、こんなことになってるわけですね。すげー。

ついでに個人的に上のメソッドがなげーなと思ったのでちょっとリファクタリングしてみました。

def included_in_action?(controller, options)
  if ary = options[:only] || options[:except]
    Array(ary).map(&:to_s).include?(controller.action_name) ^ options[:only]
  else
    true
  end
end

色々あって仕事お預け状態です。暇です。