Undefined метод '>' для nil: NilClass <NoMethodError>

Хорошо, у меня есть следующий код

 def update_state_actions
    states.each do |state|
      @state_turns[state.id] -= 1 if @state_turns[state.id] > 0 && state.auto_removal_timing == 1
    end
  end

теперь в строке...

 @state_turns[state.id] -= 1 if @state_turns[state.id] > 0 && state.auto_removal_timing == 1

он говорит об ошибке

in 'block update_state_actions' : Undefined method '>' for nil:NilClass <NoMethodError>

в чем причина ошибки? Как получилось, что > рассматривается как метод, но он является логическим оператором?

Ответы

Ответ 1

как получается > рассматривается как метод, но он является логическим оператором?

Нет проблем с этим. В Ruby, когда вы пишете выражение типа 1 + 2, внутри него понимается 1.+( 2 ): метод вызова #+ на приемнике 1 с 2 как один аргумент. Другой способ понять то же самое, что вы отправляете сообщение [ :+, 2 ] объекту 1.

в чем причина ошибки?

Теперь в вашем случае @state_turns[ state.id ] по какой-то причине возвращает nil. Таким образом, выражение @state_turns[state.id] > 0 становится nil > 0, которое, как я сказал ранее, понимается как вызов метода #> на nil. Но вы можете проверить, что NilClass, к которому принадлежит nil, не имеет метода экземпляра #>, определенного на нем:

NilClass.instance_methods.include? :> # => false
nil.respond_to? :> # => false

Исключением NoMethodError является допустимая ошибка. Поднимая эту ошибку, Ruby защищает вас: она сообщает вам, что ваш @state_turns[ state.id ] не тот, что вы предполагаете. Таким образом, вы можете исправлять свои ошибки раньше и быть более эффективным программистом. Кроме того, исключения Ruby могут быть спасены с помощью инструкции begin ... rescue ... end. Исключения Ruby, как правило, очень дружественные и полезные объекты, и вы должны научиться определять свои пользовательские исключения в своих проектах программного обеспечения.

Чтобы расширить это обсуждение немного больше, давайте посмотрим, откуда ваша ошибка. Когда вы пишете выражение типа nil > 10, которое на самом деле nil.>( 10 ), Ruby начинает поиск метода #> в цепочке поиска nil. Вы можете увидеть цепочку поиска, набрав:

    nil.singleton_class.ancestors #=> [NilClass, Object, Kernel, BasicObject]

Метод будет искать в каждом модуле цепочки предков: во-первых, Ruby проверит, существует ли #> на NilClass, затем на Object, затем Kernel и, наконец, BasicObject. Если #> не найден ни в одном из них, Ruby будет продолжен, попробовав методы method_missing, снова по порядку на всех модулях поисковой цепочки. Если даже method_missing не обрабатывает сообщение :>, будет вызвано исключение NoMethodError. Чтобы продемонстрировать, определите метод #method_missing в Object, вставив специальное сообщение, которое появится вместо NoMethodError:

class Object
  def method_missing( name, *args )
    puts "There is no method '##{name}' defined on #{self.class}, you dummy!"
  end
end

[ 1, 2, 3 ][ 3 ] > 2 
#=> There is no method '#>' defined on NilClass, you dummy!

Почему он не говорит, как NullPointerException

В Ruby такого исключения нет. Проверьте класс Ruby Exception.

Ответ 2

Он должен быть преобразован в целочисленную переменную для выполнения opercio:

  • @state_turns [state.id].to_i > 0
  • state_a = state.auto_removal_timing.to_i + 1