Bye Bye Moore

PoCソルジャーな零細事業主が作業メモを残すブログ

active_support提供のin?メソッドとpresence_inメソッドが地味に使える

active_support提供のin?メソッドとpresence_inメソッドは地味に使える子です。

まず、in?メソッドについて。
これはObjectを拡張し、渡したモノの中に自身(self)が入っていないか確認してくれます。

require 'active_support/core_ext'
1.in?(1..100)
#=> true

"lo".in?("hello")
#=> true

"".in?("おはよう")
#=> true

1.in?([2,9,1,8])
#=> true

実はほぼ同様の挙動はinclude?で実現できてしまうのですが...順番が逆です

(1..100).include?(1)
#=> true

"string".include?('s')
#=> true

[1,2,4].include?(1)
#=> true

一方presence_in*1
in?と同様Objectを拡張し、渡したものの中に自身が存在すればselfを返してくれます。

require 'active_support/core_ext'

"".presence_in("おはよう")
#=> "お"

42.presence_in(1..100)
#=> 42

実際のところ

実際、元の実装を見に行くとinclude?を使っている事がわかります*2

class Object
  # Returns true if this object is included in the argument. Argument must be
  # any object which responds to +#include?+. Usage:
  #
  #   characters = ["Konata", "Kagami", "Tsukasa"]
  #   "Konata".in?(characters) # => true
  #
  # This will throw an ArgumentError if the argument doesn't respond
  # to +#include?+.
  def in?(another_object)
    another_object.include?(self)
  rescue NoMethodError
    raise ArgumentError.new("The parameter passed to #in? must respond to #include?")
  end

  # Returns the receiver if it's included in the argument otherwise returns +nil+.
  # Argument must be any object which responds to +#include?+. Usage:
  #
  #   params[:bucket_type].presence_in %w( project calendar )
  #
  # This will throw an ArgumentError if the argument doesn't respond to +#include?+.
  #
  # @return [Object]
  def presence_in(another_object)
    self.in?(another_object) ? self : nil
  end
end

自分で書いても良いのかもしれませんが、
テスト済というのはデカイです。

*1:これはクエスチョンマーク不要です。

*2:事例でらき☆すたを持ってきたお友達がいらっしゃるようですね...