インスタンス変数が@foo
あり、文字列を取得するコードを書きたい'foo'
ヒントはありますか?
オブジェクトへの参照しかない場合は、きれいに行うことはできません。
def foo
bar @something
end
def bar(value)
value # no clean way to know this is @something
end
私が考えることができる唯一のハックは、 のすべてのインスタンス変数をループしself
て、一致を探すことです。しかし、これは非常に厄介なアプローチであり、遅くなる可能性があります。
def bar(value)
instance_variables.each do |ivar_name|
if instance_variable_get(ivar_name) == value
return ivar_name.to_s.sub(/^@/, '') # change '@something' to 'something'
end
end
# return nil if no match was found
nil
end
@something = 'abc123'
bar @something # returns 'something'
# But passing the same value, will return a value it's equal to as well
bar 'abc123' # returns 'something'
これが機能するinstance_variables
のは、インスタンス変数の名前であるシンボルの配列を返すためです。
instance_variables
#=> [:@something, :@whatever]
そしてinstance_variable_get
、その名前で値を取得できます。
instance_variable_get :@something # note the @
#=> 'abc123'
2 つの方法を組み合わせると、目的に近づくことができます。
賢く使ってください。これに基づくソリューションを使用する前に、必要がないようにリファクタリングできるかどうかを確認してください。メタプログラミングは格闘技のようなものです。それがどのように機能するかを知っている必要がありますが、可能な限り使用しないように規律を持ってください。
Ruby では、オブジェクトのみを操作できます。変数 (インスタンス変数を含む) はオブジェクトではありません。
さらに、この場合、マジックメソッドに何を返してもらいたいですか:
foo = Object.new
bar = foo
@baz = bar
@qux = bar
magic_method(foo) # what should the return value be and how would it know?
このメソッドを呼び出してinstance_variables
、オブジェクトのすべてのインスタンス変数の名前を取得できます。ただし、インスタンス変数は、初期化された後にのみそのリストに含まれることに注意してください。
>> class A; attr_accessor :foo; end
=> nil
>> a = A.new
=> #<A:0x103b310b0>
>> a.instance_variables
=> []
>> a.foo = 42
=> 42
>> a.instance_variables
=> ["@foo"]