2017-01-20 5 views
4

в рубиновой классе я перезаписать три метода, и, в каждом методе, я в основном делаю то же самое:Переписать подобные методы, короче синтаксис

class ExampleClass 

    def confirmation_required? 
    is_allowed && super 
    end 

    def postpone_email_change? 
    is_allowed && super 
    end 

    def reconfirmation_required? 
    is_allowed && super 
    end 

end 

Есть ли более компактный синтаксис? Как я могу сократить код?

+3

Если ваш код работает и вы хотите просмотреть код, перейдите к [codereview.se]. –

+0

Мне было бы интересно увидеть решение, которое использовало технику, аналогичную всем методам рельсов. Что-то вроде «require_confirmation: postpone_email_change?: Reconfirmation_required?: Confirm_required?» –

+0

@JeffPrice рельсы смешны, но все же, пожалуйста: 'Extender = Module.new {def require_confirmation (* methods); methods.each {| m | define_method m {| * args, & cb | is_allowed && super (* args, & cb)}}; конец ; module_function: require_confirmation} '. Теперь вызовите 'Extender.require_confirmation: postpone_email_change ?,: reconfirmation_required ?,: confirm_required?' Или 'prepend'' ExampleClass.singleton_class' с 'Extender' и вызывать его без явного пространства имен. – mudasobwa

ответ

8

Как использовать псевдоним?

class ExampleClass 

    def confirmation_required? 
    is_allowed && super 
    end 

    alias postpone_email_change? confirmation_required? 
    alias reconfirmation_required? confirmation_required? 
end 
+0

Вы попробовали этот код? Было бы интересно узнать, действительно ли «псевдоним» называет правильный супер. – Felix

+0

Проблема с вашим ответом: это неправильно. Предположим, что класс А; def x; ставит «в A # x»; конец; def y; помещает «в A # y»; конец; конец; класс B " в A # x "'. Хеунджу (и @ Феликс), почему ты не проверил? –

1
class ExampleClass 
    %i|confirmation_required? 
    postpone_email_change? 
    reconfirmation_required?|.each do |m| 

    define_method m do |*args, &cb| 
     is_allowed && super(*args, &cb) 
    end 
    end 
end 

Примечание:%i|symbol1 symbol2| является аббревиатурой для [:symbol1, :symbol2] - это рубин 2.0+ синтаксис для создания списка символов из слов.

+0

Синтаксис '% i' может потребовать объяснения для новых пчел. – Felix

+2

Mudsie, вы не можете использовать неявный 'super' с' define_method' (вызов '' RuntimeError: неявный перенос аргумента super из метода, определенного define_method(), не поддерживается. Указать все аргументы явно. "') К счастью, поскольку 'm' не имеет аргументов и никакого блока, исправление легко: замените' super' на 'super()'. –

+1

@CarySwoveland спасибо! Обновлено. Аргументы могут быть легко перепрофилированы в общем виде, однако, см. Обновление. – mudasobwa

0

eval подход. Рассматривается запах кода, но в этом случае имеет лучшую читаемость. Также легче понять для менее опытных людей в вашей команде.

class ExampleClass 
    WRAPPED_METHODS = %i(
    confirmation_required? 
    postpone_email_change? 
    reconfirmation_required? 
) 

    WRAPPED_METHODS.each do |method_name| 
    class_eval(" 
     def #{method_name} 
     is_allowed && super 
     end 
    ") 
    end 
end 
+0

Итак, вы взяли мой [в настоящий момент неправильный, теперь это правильно, спасибо @CarySwoveland] ответьте, усугубляйте его смешным призывом к 'eval', где он полностью не принадлежит, и размещен как ваш собственный? В чем причина этого? Если вы хотите выполнить строку здесь, используйте 'class_eval' /' instance_eval'. Кроме того, он ** не читает лучше ** без подсветки синтаксиса. – mudasobwa

+0

Я работал над этим конкретным типом проблемы несколько дней назад, поэтому нет, мой ответ не «вдохновлен» вашим. Одна из проблем, которые я испытывал, заключалась в том, что мой код будет передан команде младших программистов, и им было бы сложно найти причуды 'define_method' и' super() '. – fylooi

+0

Итак, ваша забота состоит в том, чтобы воспитывать юниоров с помощью 'eval' вместо правильных рубиновых решений повсюду, потому что трудно понять' super'? Понял. – mudasobwa

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