2010-10-01 4 views
2

Я создаю некоторые методы на лету. Тело метода зависит от определенных критериев. Я полагался на class_eval для генерации условного кода.Условный код в блоке define_method

%Q{ 
    def #{name} 
    #{ 
    (name != "password") ? "attributes[:#{name}]" : 
         "encrypt(attributes[:#{name}])" 
    } 
    end 
} 

Недавно я начал использовать define_method. Как создать условные блоки кода при использовании define_method?

Edit 1

Вот возможные подходы, которые я рассмотрел:

1) Проверка имени на во время выполнения:

define_method(name) do  
if name == password 
    decrypt(attributes[name])  
else 
    attributes[name] 
end 
end 

Это не является предпочтительным методом, как проверка выполняется во время выполнения.

2) Условное определение всего метода.

if (name == "password") 
define_method(name) do  
    decrypt(attributes[name])  
end 
else 
define_method(name) do  
    attributes[name] 
end 
end 

Этот подход имеет недостаток, заключающийся в необходимости повторять блок кода просто поменять небольшую часть (как мой фактический метод имеет несколько строк кода).

ответ

3

Я думаю, что из-за закрытия вы можете сделать что-то вроде этого:

define_method name do 
    if name=='password' 
     decrypt(attributes[name]) 
    else 
     attributes[name] 
    end 
    end 

Но проблема есть в том, что если будет оцениваться при каждом вызове метода. Если вы хотите избежать этого, вам нужно будет передать разные блоки до define_method для разных поведений. например

if name=='password' 
    define_method(name) { decrypt(attributes[name]) } 
else 
    define_method(name) { attributes[name] } 
end 

попеременно вы могли бы пройти lambda выбранный если заявление.

define_method(name, name=='password' ? lambda { decrypt(attributes[name]) } : lambda { attributes[name] } 

О чем нужно думать, define_method может быть медленнее, чем использование eval.

+0

+1, Я рассмотрел оба подхода, которые вы предложили. По очевидным причинам я отклонил первый подход. Второй подход - это то, что я делаю сейчас, но я должен повторить свой код дважды. Фактический метод, который я добавляю, имеет более крупный метод. так что это глазная язва. –

+0

Мне интересно узнать о последнем предложении, есть ли у вас какие-либо ссылки, которые говорят об этой проблеме? –

+0

После некоторого поиска, похоже, что это немного медленнее, чем использование 'def', но eval не так уж и отличается. Я не нашел никаких недавних тестов, но что-то вроде этого очень зависит от переводчика. – BaroqueBobcat

Смежные вопросы