Ruby не удается переопределить метод отправки

#ruby #metaprogramming #eventmachine

#ruby #метапрограммирование #eventmachine

Вопрос:

Это немного сложно объяснить, но, похоже, мне иногда не удается переопределить метод ‘send’ в моем приложении. Я создаю довольно большое приложение на основе EventMachine и иногда, глубоко в недрах моего кода, я решаю определить метод ‘send’ в одном из моих классов. Когда я позже пытаюсь использовать этот метод, я обычно получаю исключение, которое выглядит примерно так TypeError: <parameter> is not a symbol , например, следующее (случается, что оно вызвано требуемым AMQP gem (не моим), но этот вопрос более общий):

 Exception caught: TypeError - #<AMQ::Protocol::MethodFrame:0x000001008434f0 @payload="x002x00x14x00x00x01atamq.topicx00x01x00x00x00x00", @channel=1> is not a symbol
/Users/mlartz/.rvm/gems/ruby-1.9.2-p180@rflow-component-devel/gems/amq-client-0.7.0.alpha27/lib/amq/client/queue.rb:137:in `bind'
/Users/mlartz/.rvm/gems/ruby-1.9.2-p180@rflow-component-devel/gems/amqp-0.8.0.rc12/lib/amqp/queue.rb:282:in `block in bind'
/Users/mlartz/.rvm/gems/ruby-1.9.2-p180@rflow-component-devel/gems/eventmachine-1.0.0.beta.3/lib/em/deferrable.rb:47:in `call'
/Users/mlartz/.rvm/gems/ruby-1.9.2-p180@rflow-component-devel/gems/eventmachine-1.0.0.beta.3/lib/em/deferrable.rb:47:in `callback'
  

Это некорректная строка:

 @connection.send(Protocol::Queue::Bind.encode(@channel.id, @name, exchange_name, routing_key, nowait, arguments))
  

В этом конкретном случае класс @connection объекта определил send метод, который принимает AMQ::Protocol::MethodFrame . Однако, похоже, что каким-то образом вызывается метод по умолчанию Object#send (который ожидает символ, отсюда и исключение).

Ранее в процессе разработки у меня была такая же проблема с одним из моих пользовательских классов, которая была решена путем изменения имени моего метода ‘send’ на ‘send_message’.

Итак, поскольку это немного общий вопрос, вопрос в том, какие вещи могут помешать моей способности вызывать пользовательский send метод для объекта, который его определил?

К вашему сведению: я использую Ruby 1.9.2p180 в OSX.

Комментарии:

1. Это происходит только в процессе разработки? Возможно ли, что проблема в перезагрузке класса, поскольку классы не кэшируются при разработке, если вы добавляете методы во время выполнения, класс может быть перезагружен без ваших вновь определенных методов?

2. Я не говорю, что рекомендую это, но вы могли бы Object.class_eval { undef :send } отменить определение Object#send . В тех случаях, когда он вам все еще нужен, он доступен как Object#__send__ .

3. Стив, на данный момент у меня только разработка. Есть ли что-то, чего я не понимаю в Ruby, rvm, bundler, что выполняло бы перезагрузку класса без моего ведома, или я должен был бы четко указать на это?

4. И на самом деле, при воспроизведении кажется, что это может быть nil проблема с объектом, т. Е. если объект-получатель есть, nil тогда он попытается выполнить Object#send . Так что, возможно, это было просто мое замешательство.

5. @Майкл Л. Артс. В среде разработки классы не кэшируются и перезагружаются для каждого запроса. В производственных средах классы кэшируются, поэтому у вас нет накладных расходов на загрузку всех классов для каждого запроса. Это контролируется в файлах конфигурации среды путем изменения значения config.cache_classes

Ответ №1:

Не рекомендуется использовать или переопределять send метод. Object.send — это очень простой метод в модуле ядра Ruby. Однажды у меня возникла серьезная проблема, когда я определял Message.send класс, и в итоге я использовал другое имя, например Message.transmit . В Ruby on Rails это зарезервированное слово.

Комментарии:

1. Примерно так я и думал. Я предполагаю, что симптомом этой проблемы является сбивающее с толку TypeError исключение, когда фактически существует nil объект receiver ( nil получает send ).