2010-04-02 7 views
0

Я недавно начал проект в Ruby on Rails. Раньше я делал все свои проекты в Python, но решил дать Ruby выстрел.Ruby switch like idiom

В проектах, которые я написал в Python Я использовал миленький технику объяснена правильный ответ на этот пост:

Dictionary or If statements, Jython

Я использую эту технику из-за Python не имеющие природную функцию переключателя и также избавиться от больших блоков if else

Я пытаюсь восстановить воссозданный выше метод в Ruby, но, похоже, не может его получить.

Может ли кто-нибудь помочь мне?

+1

Ruby имеет выражение для случая. почему ты хочешь сделать это? –

+0

Его больше просто любопытство, чем что-либо еще :) – RailsSon

+0

При преобразовании кода с одного языка на другой рекомендуется писать новый код идиоматически для нового языка. Другими словами, используйте свои конструкции вместо того, чтобы грубо заставлять конструкции других языков. В этом конкретном случае Ruby 'Object # send' будет делать это, но я думаю, что для чтения и обслуживания кода вам, вероятно, будет лучше использовать операторы' case/when'. Они облегчают просмотр происходящего, который окупается через год, когда вам нужно что-то добавить. –

ответ

2

Если вам нужно только вызвать метод по его имени, хранящегося в строке, стандартный рубин способ сделать это с помощью метода Object#send:

def extractTitle dom 
    puts "title from #{dom}" 
end 

def extractMetaTags dom 
    puts "metatags from #{dom}" 
end 

dom = 'foo' 

type = 'extractTitle' 
send type, dom 
#=> title from foo 
type = 'extractMetaTags' 
send type, dom 
#=> metatags from foo 

В противном случае, вы можете использовать case заявление Руби, как уже было предложено.

+0

вам не нужен вызов #to_sym (send принимает как строки, так и символы) – horseyguy

+0

Я просто не был уверен в более ранних версиях Ruby. Спасибо, сейчас я обновлю ответ. –

2

В то время как ничто не мешает вам использовать подход на основе классов, почему бы не избежать заявления rubys case?

case thing 
when 'something' 
    do_something 
when 'nothing' 
    do_nothing 
else 
    do_fail 
end 
+0

Я что-то пропустил с помощью 'method_missing'? Разумеется, объект никогда не сможет ответить на вызов, если он достиг метода method_missing. –

+0

Действительно! Хорошо поймал. Так как я все-таки определял методы, 'method_missing' только когда-либо вызывал исключение. Я обновлю, чтобы удалить пример избыточного кода. – ezpz

0

Как говорили другие, в Ruby есть альтернативные способы сделать это, но если вам просто интересно, то эквивалент этого подхода Python в Ruby (используя Object#send после определения имени метода):

class MyHandler 
    def handle_test(arg) 
    puts "handle_test called with #{arg}" 
    end 

    def handle_other(arg) 
    puts "handle_other called with #{arg}" 
    end 

    def handle(type, *args) 
    method_name = "handle_#{type}" 
    if respond_to? method_name 
     send(method_name, args) 
    else 
     raise "No handler method for #{type}" 
    end 
    end 
end 

Вы можете сделать:

h = MyHandler.new 
h.handle 'test', 'example' 
h.handle 'other', 'example' 
h.handle 'missing', 'example' 

и результат будет:

handle_test called with example 
handle_other called with example 
handle.rb:15:in `handle': No handler method for missing (RuntimeError) 
     from handle.rb:23