Ruby - how to raise the same error for multiple methods without writing it multiple times?

Suppose I create a calculator class that works by manipulating elements in an array. In this class, I define several methods: addition, subtraction, multiplication, division. I want each method to raise the same error if there are only 1 or fewer elements in the array, for example:

class Calculator
# ...
def add
  if @array.length < 2
    raise 'Not Enough Elements'
  else
    @array << @array.pop + @array.pop
  end
end
# ...
end

I could write a condition to raise an error in every method, but it seems very tedious and non-Ruby. Will there be a way to apply the raised error to all the methods that will be needed to save everything that prints?

+4
source share
3 answers

, :

class Calculator
  def add
    check_array_length
    # rest of the method
  end

  private

  def check_array_length
    raise 'Not Enough Elements' if @array.length < 2
  end
end

@array initialize, , , - @array:

class Calculator
  def initialize(array)
    raise 'Not Enough Elements' if array.length < 2

    @array = array
  end
end
+3

:

module Validator
  [:add, :substract, :multiply, :divide].each do |method|
    define_method(method) do
      validate_array_length(2)
      super()
    end
  end

  private

  def validate_array_length(min,max=min)
    raise 'Not Enough Elements' if @array.length < min
    raise 'Too Many Elements' if @array.length > max
  end
end

class Calculator
  prepend Validator
  def initialize(*values)
    @array = values
  end

  def add
    @array << @array.pop + @array.pop
  end

  # def substract ....
end

c = Calculator.new(3,2)
c.add
c.add
# => calculator.rb:12:in `validate_array_length': Not Enough Elements (RuntimeError)
+1
class Calculator
  def initialize(arr)
    @arr = arr
  end

  def add;      binary(:+);    end
  def subtract; binary(:-);    end
  def multiply; binary(:*);    end
  def divide;   binary(:/);    end
  def power;    binary(:**);   end
  def modulo;   binary(:%);    end
  # ... (others)

  def negate;   unary(:-@);    end
  def odd?;     unary(:odd?);  end
  def even?;    unary(:even?); end
  def to_f;     unary(:to_f);  end
  # ... (others)

  private

  def binary(op)
    raise ArgumentError, 'Too few elements' if @arr.length < 2
    @arr.pop.send(op, @arr.pop)
  end

  def unary(op)
    raise ArgumentError, 'Too few elements' if @arr.length.zero?
    @arr.pop.send(op)
  end
end

#                      add  neg   mod   pow   div  mult     sub     add 
calc = Calculator.new [  1,   5,  2,3,  4,5,  6,7,  8,9,  10,11,  12,13]
  #=> #<Calculator:0x007fa192030968 @arr=[1, 5, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]> 

calc.add       #=> 25  (13+12) 
calc.subtract  #=> 1   (11-10) 
calc.multiply  #=> 72  (8*9)   
calc.divide    #=> 1   (7/6)
calc.power     #=> 625 (5**4)
calc.modulo    #=> 1   (3%2)
calc.negate    #=> -5  (5)
calc.add       #=> ArgumentError: Too few elements

, RPN. , , , . binary :

  def binary(op)
    raise ArgumentError, 'Too few elements' if @arr.length < 2
    @arr << @arr.pop.send(op, @arr.pop)
    @arr[-1]
  end

@arr[-1], . unary .

, ,

def pop
  @arr.pop
end

def push(n)
  @arr << n
end

def swap
  @arr[-1], @arr[-2] = @arr[-2], @arr[-1]
end

def rotate
  @arr.rotate
end

, , ( ) @arr , unshift/shift, push/pop.

+1
source

Source: https://habr.com/ru/post/1661312/


All Articles