2015-07-03 2 views
5

У меня проблема с поиском через хэш, где мои значения являются методами. Я просто не могу запустить метод, где plan_type соответствует ключу.Поиск через хэш в рубине со значениями, которые являются методами

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 

В настоящее время, если я перехожу в «баре», как plan_type, каждый метод будет работать, как я могу работать только только метод plan_is_bar?

+0

Есть много способов для достижения эффекта вы хотите, кажется (вызов метода в зависимости от имени типа или другой логики). Если вы собираетесь немедленно вызвать метод, такой хеш может быть не самым простым способом. Тем не менее, это может быть полезно, если вы хотите отложить вызов до самого последнего. –

ответ

8

что об этом варианте?

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 

Использование лямбды или проки является хорошим способом, чтобы сделать вещи ленивым, потому что они выполняются только тогда, когда они получают методу call

Из-за этого вы можете использовать -> (лямбда буквальное), как легкий обертки вокруг, вероятно, тяжелые расчеты и call это только когда вам нужно.

+5

Вы также можете немного рассказать о лямбдах и о том, как они решают проблему OP с его кодом, делая все возможные вызовы методов, прежде чем возвращать правильное значение. Самое главное, вы не внесли значения здесь в методы (что на самом деле невозможно в Ruby), но Procs, содержащие правильные вызовы методов (и это также замыкания). –

+0

У вас есть небольшая проблема с аргументами 'method', так как' method (: har, "bob") 'будет вызывать исключение' ArgumentError'. Я имел дело с этим, предоставляя 'plan' произвольное значение по умолчанию. В дополнение к точке Нейла вам нужно только создать (а затем вызвать) один лямбда: 'def method (plan_type, plan = nil, user); if plan_type ==: har; -> (пользователь) {plan_is_har (пользователь)} .call user; еще; case plan_type; когда: foo then -> (plan, user) {plan_is_foo (план, пользователь)}; когда: bar then -> (plan, user) {plan_is_bar (план, пользователь)}; когда: waa then -> (plan, user) {plan_is_waa (план, пользователь)}; end.call plan, пользователь; конец; end'. –

1

очень простое решение:

Код

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 

Можно, конечно, использовать хэш вместо case заявления.

Пример

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 
Смежные вопросы