web-dev-qa-db-ja.com

nil:NilClass <NoMethodError>の未定義メソッド '>'

OK私は次のコードを持っています

 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>

エラーの原因は何ですか? - どうして >はメソッドと見なされますが、論理演算子ですか?

17
Mp de la Vega

どうして>はメソッドと見なされますが、それは論理演算子ですか?

それに問題はありません。 Rubyでは、1 + 2のような式を記述すると、内部的には1.+( 2 )として理解されます。単一の引数として#+を使用して、レシーバー1でメソッド2を呼び出します。同じことを理解する別の方法は、メッセージ[ :+, 2 ]をオブジェクト1に送信することです。

エラーの原因は何ですか?

ここで、@state_turns[ state.id ]は何らかの理由でnilを返します。したがって、式@state_turns[state.id] > 0nil > 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例外が発生します。デモンストレーションのために、Objectの代わりに表示されるカスタムメッセージを挿入して、NoMethodError#method_missingメソッドを定義しましょう。

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 クラスを確認してください。

52
Arup Rakshit

演算子を実行するには、整数変数に変換する必要があります。

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