Search code examples
rubypattern-matchingcase

Ruby case statements with multiple variables


Ruby has a fairly powerful case..when..else construct for when you need to match criteria against a single variable. What is the "canonical" way to match criteria against multiple variables without simply nesting case statements?

Wrapping multiple variables in an array (like [x, y]) and matching against it isn't equivalent, because Ruby won't apply the magical case === operator to the elements of the array; the operator is only applied to the array itself.

I'm going to go ahead and respond with a community-wiki answer with a (defeated) stab at this question.


Solution

  • This is a simplistic way to add ===:

    class Array
      def ===(other)
        return false if (other.size != self.size)
    
        other_dup = other.dup
        all? do |e|
          e === other_dup.shift
        end
      end
    end
    
    [
      ['foo', 3],
      %w[ foo bar ],
      %w[ one ],
      []
    ].each do |ary|
    
      ary_type = case ary
      when [String, Fixnum] then "[String, Fixnum]"
      when [String, String] then "[String, String]"
      when [String] then "[String]"
      else
        "no match"
      end
    
      puts ary_type
    
    end
    
    # >> [String, Fixnum]
    # >> [String, String]
    # >> [String]
    # >> no match