Как стать автором
Обновить

Самозванцы в Ruby или что такое Proxy Class

Время на прочтение1 мин
Количество просмотров660
Как вам такое проявление «полиморфизма» в rails?
contact.class
=> NilClass
puts "OK" if contact
OK
=> nil
puts "OK" unless contact
=> nil
contact == nil
=> true
puts "OK" if contact
OK
=> nil
puts "OK" if nil
=> nil


Такой феномен возникает во многих ситуациях и связан он с использованием паттерна проектирования Proxy Class. Конкретно в случае ActionView он возникает при использовании deprecated методов. Подробнее в activesupport/lib/active_support/deprecation.rb (Реализация proxy классов DeprecationProxy и наследников) и в actionpack/lib/action_view/renderable_partial.rb (Их использование).

Смоделировал такую ситуацию для наглядности:
class ProxyClass
silence_warnings { instance_methods.each { |m| undef_method m unless m =~ /^__/ } }

def initialize(target)
@target = target
end

private
def method_missing(called, *args, &block)
@target.__send__(called, *args, &block)
end
end

Смотрим:

>> @nil_object1 = nil
=> nil
>> @nil_object2 = ProxyClass.new(@nil_object1)
=> nil
>> @nil_object1.object_id
=> 4
>> @nil_object2.object_id
=> 4
>> @nil_object2.__id__
=> 2198992980
>> @nil_object1.__id__
=> 4


Как видно, поскольку для ^__ undef не делали (в DeprecationProxy тоже не делают), то вычислить таких самозванцев можно по __id__
Теги:
Хабы:
Всего голосов 10: ↑9 и ↓1+8
Комментарии0

Публикации