Search code examples
rubyclassobjectmonkeypatching

Is it a bad idea to monkey patch Object to have a more natural way for testing if an element is in an array?


Bothered by that we could test in Ruby whether an array (or another Enumerable) contains a value with the include? method...

puts %w(one two three four).include?("two")
# => true
puts %w(one two three four).include?("five")
# => false

... but not directly test whether a value is included in an array (semantically identical, but not part of the language)...

puts "two".in?( %w(one two three four) )
puts "five".in?( %w(one two three four) )

I thought about monkey patching Object to have a handy Object#in? method, something similar to:

class Object
  def in?(array)
    return false unless array.respond_to?(:include?)  # Or perhaps raise an error.
    return array.include?(self)
  end
end

With that method definition on Object, things like

"two".in?( %w(one two three four) )
# => true
:nuts.in?( [:banana, :chocolate, :pie] )
# => false

work nicely, and are very close to a normal sentence expressing that test.

Frequently, I run into that if element.in?(array) is a subtly more natural expression than if array.include?(element), especially if the array is included as a literal (instead of a variable reference).

Question (while neglecting the general opinion on monkey patching): is this example of monkey patching a smart thing to do? What are specific drawbacks for having an Object#in? method, again not going into the generic pros and cons of monkey patching objects (in Ruby)?


Solution

  • Ignoring the general arguments for/against monkey patching in Ruby, the code you describe is an example of a convenience method to help with your readability. Arguments against its inclusion also apply to the generic case as well, so there doesn't appear to be a specific drawback. Technically, this method is already included in the Ruby on Rails framework, so the authors shared your view in supporting it as a natural expression.