2015-07-03 6 views
5

Ich habe ein Problem bei der Suche durch einen Hash, wo meine Werte Methoden sind. Ich möchte nur die Methode ausführen, wo plan_type den Schlüssel entspricht.Durchsucht einen Hash in Ruby mit Werten, die Methoden sind

def method(plan_type, plan, user) 
    { 
    foo: plan_is_foo(plan, user), 
    bar: plan_is_bar(plan, user), 
    waa: plan_is_waa(plan, user), 
    har: plan_is_har(user) 
    }[plan_type] 
end 

Zeit, wenn ich in „bar“ als plan_type passieren, wird jede Methode ausgeführt, wie kann ich nur laufen gerade die plan_is_bar Methode?

+0

Es gibt viele Möglichkeiten, um den Effekt, den Sie (rufen Sie eine Methode in Abhängigkeit von einem benannten Typ oder einem anderen Logik) scheinen zu wollen, zu erreichen. Wenn Sie die Methode sofort aufrufen, ist ein solcher Hash möglicherweise nicht der einfachste Weg. Es kann jedoch nützlich sein, wenn Sie den Anruf erst später vornehmen möchten. –

Antwort

8

was ist mit dieser Variante?

def method(plan_type, plan, user) 
    { 
    foo: -> { plan_is_foo(plan, user) }, 
    bar: -> { plan_is_bar(plan, user) }, 
    waa: -> { plan_is_waa(plan, user) }, 
    har: -> { plan_is_har(user) } 
    }[plan_type].call 
end 

lambdas oder Procs ist eine gute Art und Weise Dinge faul zu machen, weil sie nur dann ausgeführt werden, wenn sie Verfahren call

Aus diesem Grund erhalten Sie -> (Lambda wörtliche) als leichte Wrapper um wahrscheinlich verwenden können schwere Berechnungen und call es nur, wenn Sie brauchten.

+5

Sie könnten auch ein wenig über die Lambdas erklären und wie sie das Problem des OP mit seinem Code lösen, indem Sie alle möglichen Methodenaufrufe machen, bevor Sie den korrekten Wert zurückgeben. Am wichtigsten ist, dass Sie die Werte hier nicht in Methoden umgesetzt haben (was in Ruby nicht wirklich möglich ist), sondern in Procs, die die korrekten Methodenaufrufe enthalten (und diese sind auch Closures). –

+0

Sie haben ein kleines Problem mit 'method's Argumenten, da' method (: har, "bob") 'eine' ArgumentError' Ausnahme auslöst. Ich habe damit umgegangen, indem ich "plan" einen beliebigen Standardwert gegeben habe. Zusätzlich zu @ Neils Punkt müssen Sie nur ein Lambda erstellen (und dann aufrufen): 'def-Methode (plan_type, plan = nil, user); wenn plan_type ==: har; -> (Benutzer) {plan_is_har (Benutzer)} .call Benutzer; sonst; Fall plan_type; wenn: foo dann -> (Plan, Benutzer) {plan_is_foo (Plan, Benutzer)}; wann: bar then -> (plan, benutzer) {plan_is_bar (plan, benutzer)}; Wann: waa then -> (Plan, Benutzer) {plan_is_waa (Plan, Benutzer)}; end.call Plan, Benutzer; Ende; Ende. –

1

Eine sehr einfache Lösung:

-Code

def method(plan_type, plan=nil, user) 
    m = 
    case plan_type 
    when "foo" then :plan_is_foo 
    when "bar" then :plan_is_bar 
    when "waa" then :plan_is_waa 
    when "har" then :plan_is_har 
    else nil 
    end 

    raise ArgumentError, "No method #{plan_type}" if m.nil? 
    (m==:plan_is_har) ? send(m, user) : send(m, plan, user) 
end 

Sie könnte natürlich einen Hash anstelle einer case Anweisung verwenden.

Beispiel

def plan_is_foo plan, user 
    "foo's idea is to #{plan} #{user}" 
end 

def plan_is_bar plan, user 
    "bar's idea is to #{plan} #{user}" 
end 

def plan_is_waa plan, user 
    "waa's idea is to #{plan} #{user}" 
end 

def plan_is_har user 
    "har is besotted with #{user}" 
end 

method "foo", "marry", "Jane" 
    #=> "foo's idea is to marry Jane" 

method "bar", "avoid", "Trixi at all costs" 
    #=> "bar's idea is to avoid Trixi at all costs" 

method "waa", "double-cross", "Billy-Bob" 
    #=> "waa's idea is to double-cross Billy-Bob" 

method "har", "Willamina" 
    #=> "har is besotted with Willamina" 

method "baz", "Huh?" 
    #=> ArgumentError: No method baz