Help refactoring this nasty Ruby if/else statement

前端 未结 5 1766
无人共我
无人共我 2021-02-02 01:57

So I have this big, hairy if/else statement. I pass a tracking number to it, and then it determines what type of tracking number it is.

How can I simplify this thing? Sp

5条回答
  •  遇见更好的自我
    2021-02-02 02:49

    Whilst longer than jtbandes solution, you might like this as it's a bit more declarative:

    class Condition
      attr_reader :service_name, :predicate
    
      def initialize(service_name, &block)
        @service_name = service_name
        @predicate = block
      end
    end
    
    CONDITIONS = [
      Condition.new('ups')   { |n| n[1] == 'Z' },
      Condition.new('dhl')   { |n| n[0] == 'Q' },
      Condition.new('fedex') { |n| n[0..1] == '96' && n.size == 22 },
      Condition.new('ups')   { |n| n[0] == 'H' && n.size == 11 },
      Condition.new('ups')   { |n| n[0] == 'K' && n.size == 11 },
      Condition.new('dhlgm') { |n| n.size == 17 },
      Condition.new('usps')  { |n| [13, 20, 22, 30].include?(n.size) },
      Condition.new('fedex') { |n| [12, 15, 19].include?(n.size) },
      Condition.new('dhl')   { |n| [10, 11].include?(n.size) },
    ]
    
    def tracking_service(tracking_number)
      result = CONDITIONS.find do |condition|
        condition.predicate.call(tracking_number)
      end
    
      result.service_name if result
    end
    

    I haven't dealt with the check_response method call here as I feel you should probably handle that elsewhere (assuming it does something other than return a tracking service name).

提交回复
热议问题