2016-07-07 6 views
2

Я пытаюсь выставить некоторые методы классу на основе значений в его атрибуте порядка, который может быть чем-то вроде ['top', 'bottom', 'right', 'lower-right'].Ruby: методы метапрограммирования, основанные на атрибуте модели

Во-первых, мой класс удаляет из этого массива все, что отвечает пустым, так как:

def order 
    order.split(' ').delete_if do |o| 
    send(o).blank? if respond_to? o 
    end 
end 

После этого, я хочу, чтобы «разоблачить» top (ради пример) в качестве метода класса. Я попытался вещи, как это в initialize метод:

order.each do |o| 
    V1_ATTRIBUTES << o.to_sym 
    define_method(o) do |a| 
    send(a).blank? ? '' : send(a) 
    end 
end 

Но o не определен, когда класс не instantialised, а-ля:

<NameError: undefined local variable or method `o' for #<Class:#<APIDocument:0x007fb8123609f8>>> 

Кто-нибудь есть какие-либо успеха с лучшим способ получить этот результат?

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

+0

Есть ли бесконечная рекурсия в реализации метода 'order'? – Aetherus

+0

Нет, это было упрощено для этого сообщения. :) –

ответ

2

Вы можете определить методы одноточечного (методы для каждого объекта).

def order 
    orders.split(' ').map{|o| send(o)}.compact.each do |o| 
    singleton_class.send(:define_method, o) do 
     send(o).to_s 
    end 
    end 
end 

Но, как вы можете видеть, это только испортило ваш код. Поэтому не злоупотребляйте метапрограммированием, используйте его с умом.

+0

Ах! Одиночные методы. Спасибо! –

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