Bye Bye Moore

猫マンション建築の野望を胸に零細事業主として資本主義の荒波に漕ぎ出したアラサー男の技術メモ

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:事例でらき☆すたを持ってきたお友達がいらっしゃるようですね...