2017-07-20 4 views
2

j'ai rencontré un problème avec la complexité cyclomatique trop élevée pour cette méthode rubis:Une meilleure façon d'écrire des méthodes qui renvoient des méthodes basées sur un ensemble de conditions dans 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 

Est-il possible de écrire ceci sans avoir à utiliser eval?

Répondre

4

Essayez ceci:

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() vous permet d'appeler une méthode par nom en utilisant des chaînes ou des symboles. Le premier paramètre est le nom de la méthode; Les paramètres suivants sont simplement transmis à la méthode appelée.

+2

peut-être '# public_send' en fonction de la mise en œuvre en particulier s'il y a aussi des méthodes privées 'find_XXX' – engineersmnky

2

Il n'y a rien de mal à regarder les noms de méthode ou de classe si vous avez besoin une certaine flexibilité:

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 

Vous pouvez également rechercher procs, quelque chose comme

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