Array#extract_options!で引数からオプションをひっこぬく٩( ‘ω’ )و

Railsでのvalidationを設定する時はこう書きますよね?

validates :name, :kana,
  presence: true

validatesメソッドに、symbolとhashが複数指定されています

オプション部分はHashですねー

引数とオプション(Hash)を分離したいときに大活躍するのがArray#extract_options!です

extract_options!のコードを見てみましょう

# activesupport/lib/active_support/core_ext/array/extract_options.rb
class Array
  def extract_options!
    if last.is_a?(Hash) && last.extractable_options?
      pop
    else
      {}
    end
  end
end

last.is_a?(Hash) && last.extractable_options?で配列の末尾のオブジェクトがHashかチェックしてます

HashだったらpopメソッドでHashを引っこ抜いてます

Hashでなかったら空のHashを返してます

メソッド!がついてるのは破壊的メソッドだからですね

Railsコンソールで確認してみましょう

args = [:name, :kana, {presence: true}]
options = args.extract_options!

args    #=> [:name, :kana]
options #=> {:presence=>true}

おおー、引数とoption(Hash)を分離できましたヾ( ̄∇ ̄=ノ

validatesのコードはこんなかんじ( ˘ω˘)

# activemodel/lib/active_model/validations/validates.rb
def validates(*attributes)
  defaults = attributes.extract_options!.dup
  [...]
end

extract_options!のコードを見ればわかりますが、Hashは末尾に指定しないとダメなので気を付けよう

[:name, {presence: true}, :kana].extract_options! #=> {}

Happy Hacking٩( ‘ω’ )و