Techioz Blog

インスタンス変数を表すシンボルがある場合、インスタンス変数が設定されているかどうかをどのように確認できますか?

概要

Remove_instance_variable(instance_variable) を使用したいのですが、ここで、instance_variable には :@some_variable という形式のシンボルが含まれていますが、最初にインスタンス変数 (例: @some_variable が存在する) を確認したいと思います。

定義されていますか?もちろん、instance_variable は「local-variable」を返すので、それは役に立ちません。

たとえinstance_variableの内容を取得できたとしても、defineを効果的に使用するには? :@some_variable は、シンボルが定義されていることを示しているため、「expression」を返します。 (これまで使用したことのない記号であっても、このコンテキストではすべての記号が「式」を返します。)

eval を使用すると、シンボルが実際のインスタンス変数に置き換えられ、機能し、nil または “instance-variable” を返します。

eval("defined? #{instance_variable}")

しかし、eval に対する強い嫌悪感を考えると (変数にユーザーが送信した値が含まれている可能性がある場合には当然のことですが)、可能であれば別の解決策を見つけたいと思います。たとえ、instance_variable にユーザーが送信したデータが含まれる可能性がないことを徹底的に確認したとしても、私の後からコードを見る人は皆、立ち止まって「なぜここで eval が使われているの?」と疑問に思うでしょう。

インスタンス変数内のシンボルによって参照されるインスタンス変数が定義されているかどうかを確認する別の方法はありますか?

解決策

オブジェクトには、インスタンス変数を取得、設定、確認、リスト表示、および削除するための 5 つのメソッドが実装されています。

インスタンス変数の定義?あなたが探しているものは次のとおりです:

name = :@foo
instance_variable_defined?(name) #=> false

@foo = nil
instance_variable_defined?(name) #=> true

このメソッドは、nil になる可能性のある値のメモ化を実装する場合にも役立ちます。

def foo
  return @foo if instance_variable_defined?(:@foo)
  
  @foo = expensive_operation_that_could_return_nil
end