ironsand ironsand - 6 months ago 10
Ruby Question

How to find a value that match a first condition from mulpitple conditions

For example there is a array like this:

a = [1,2,3]


I want to find a value that is
2
, but if that doesn't exist find a
3
and so on
5
.

result = a.find{|i| i == 2} || a.find{|i| i == 3} || a.find{|i| i == 5}


Of course the real values are more complicated, Can I write the function more succinct?

Answer

I would recommend using separate validators that encapsulate each condition. It will help you decouple your business logic.

Consider this - instead of Integer array you have Car class instances

class Car
    attr_accessor :producer, :colour, :max_speed

    def initialize(producer, colour, max_speed)
        @producer = producer
        @colour = colour
        @max_speed = max_speed
    end
end

Now you want to select cars, by max_speed, colour and lastly by producer

cars = [
    Car.new(:ford, :black, 200),
    Car.new(:fiat, :yellow, 170),
    Car.new(:renault, :green, 200),
]

instead of putting all conditions in one place, use separate validators

class ColourValidator
    def initialize(colour)
        @colour = colour
    end

    def matching?(car)
        car.colour == @colour
    end
end

class MaxSpeedValidator
    def initialize(max_speed)
        @max_speed = max_speed
    end

    def matching?(car)
        car.max_speed == @max_speed
    end
end

class ProducerValidator
    def initialize(producer)
        @producer = producer
    end

    def matching?(car)
        car.producer == @producer
    end
end

of course vaidators may be much more complex - this is just an idea

and no in one place you create validators

validators = [
    ProducerValidator.new(:renault)
]

and later in your code you may write

cars.find { |car| validators.any? { |v| v.matching?(car) } }

benefit is here you don't have to check concrete business logic but just the mechanism of returning element for which any validator matches. Additionally when new validator comes up - you just have to test its logic without reference to the rest

Comments