Почему `send` не работает с уточнением Ruby 2.0?

Почему это не работает?

module StringRefinement
  refine String do
    def bar
      length
    end
  end
end

using StringRefinement
"abcdefghijklmnopqrstuvwxyz".send(:bar)
#NoMethodError: undefined method 'bar' for "abcdefghijklmnopqrstuvwxyz":String

Может кто-нибудь объяснить, почему send здесь не работает? И есть ли способ динамически вызывать методы, определенные в уточнении? Кажется, я не могу найти хорошего, полного объяснения того, как работают уточнения в Ruby 2.0.


person Sean Mackesey    schedule 07.03.2013    source источник
comment
Потому что экспериментальный?   -  person texasbruce    schedule 07.03.2013
comment
@oldergod Правда? Я только что попробовал еще раз, скопировав и вставив приведенный выше код прямо в pry, и получил точно такую ​​​​же ошибку. Я также использую 2.0.0-p0. Вы уверены, что делаете именно то, что я написал?   -  person Sean Mackesey    schedule 07.03.2013
comment
@SeanMackesey, ты прав, мой плохой.   -  person oldergod    schedule 07.03.2013
comment
Вы знаете, что нужно делать bugs.ruby-lang.org/projects/ruby -200/вопросы   -  person oldergod    schedule 07.03.2013
comment
Он достаточно большой, чтобы разработчики никак не могли его пропустить. Я почти уверен, что это по дизайну, хотя я не понимаю причину.   -  person Sean Mackesey    schedule 07.03.2013
comment
Тоже не знаю причину, но может быть связано с этими ошибками .ruby-lang.org/projects/ruby-200/repository/revisions/38279   -  person oldergod    schedule 07.03.2013


Ответы (2)


Потому что спецификация говорит так:

Доступ к косвенным методам

Любой непрямой доступ к методу, такой как Kernel#send, Kernel#method и Kernel#respond_to?, не должен учитывать уточнения в контексте вызывающего объекта во время поиска метода.

person Jörg W Mittag    schedule 07.03.2013
comment
Спасибо, что разъяснили, что Йорг. Ты знаешь почему? - person Sean Mackesey; 07.03.2013

У меня возникает соблазн сказать: «Это сделано по замыслу». Но опять же вполне возможно, что эта конструкция не совсем стабильна. Например, функция области видимости module и class была удалена всего несколько месяцев назад.

На данный момент даже на Ruby HEAD единственный способ — использовать корень зла:

eval "puts 'abcdefghijklmnopqrstuvwxyz'.bar" # => 26

Но на самом деле, это только для лаборатории, верно? Не расцепляйте такой код, иначе котенок умрет.

person Arnaud Meuret    schedule 07.03.2013