Лучший способ написать методы, которые возвращают методы на основе набора условий в Ruby
Я столкнулся с проблемой слишком высокой сложности Cyclomatic для этого метода ruby:
def find_value(a, b, lookup_value)
return find_x1(a, b) if lookup_value == 'x1'
return find_x2(a, b) if lookup_value == 'x2'
return find_x3(a, b) if lookup_value == 'x3'
return find_x4(a, b) if lookup_value == 'x4'
return find_x5(a, b) if lookup_value == 'x5'
return find_x6(lookup_value) if lookup_value.include? 'test'
end
Есть ли способ написать это без использования eval
?
2 ответа
Решение
Попробуй это:
def find_value(a, b, lookup_value)
return find_x6(lookup_value) if lookup_value.include? 'test'
send(:"find_#{lookup_value}", a, b)
end
send()
позволяет вызывать метод по имени, используя строки или символы. Первый параметр - это имя метода; следующие параметры просто передаются вызываемому методу.
Нет ничего плохого в поиске имен методов или классов, если вам нужна некоторая гибкость:
LOOKUP_BY_A_B = {
'x1' => :find_x1,
'x2' => :find_x2,
'x3' => :find_x3,
'x4' => :find_x4,
'x5' => :find_x5,
}.freeze
def find_value(a, b, lookup_value)
method = LOOKUP_BY_A_B[lookup_value]
return self.send(method, a, b) if method
find_x6(lookup_value) if lookup_value.include? 'test'
end
Вы также можете искать Procs, что-то вроде
MY_PROCS = {
1 => proc { |a:, b:| "#{a}.#{b}" },
2 => proc { |a:, b:| "#{a}..#{b}" },
3 => proc { |a:, b:| "#{a}...#{b}" }
}.freeze
def thing(a, b, x)
MY_PROCS[x].call(a: a, b: b)
end