0

私はそれを呼び出すことができる変数を持っています@foo。文字列であると予想されるので、 を呼び出します@foo.downcase。時々それはnilで、私はこのエラーを受け取ります:

NoMethodError: undefined method `downcase' for nil:NilClass
    from (irb):4
    from /Users/schneems/.rvm/rubies/ruby-1.9.2-p290/bin/irb:16:in `<main>

私がやりたいことは、 nil が実際にあることを伝えるコードを書くことです@foo

NoMethodError: undefined method `downcase' on variable @foo, variable is a nil:NilClass
    from (irb):4
    from /Users/schneems/.rvm/rubies/ruby-1.9.2-p290/bin/irb:16:in `<main>

このようなことを行うには、変数の名前をプログラムで取得する必要があります。

質問: Ruby でプログラム的に変数の名前を取得することは可能ですか?

次のような出力を生成するものを探しています。

@foo.magical_variable_method    #=> '@foo'
bar.magical_variable_method     #=> 'bar'
AweSome.magical_variable_method #=> 'AweSome'
$wat.magical_variable_method    #=> '$wat'

変数の値は必要ありませんnil。変数の人間が読める名前が必要です。プログラムでルビー変数の名前を取得することは可能ですか?

4

4 に答える 4

1

instance_variable_get(:@ foo)を使用してシンボルからインスタンス変数を取得できます。これにより、値が得られます。

しかし、あなたはこれを行うことができます:

puts "I'm gonna call @foo now, people"
some_obj.instance_variable_get(:@foo)

見たい属性に対してmethod_missingフックを実行することもできます。@fooのアクセサーメソッドを作成せず、method_missingの呼び出しをキャッチして、instance_variable_getなどの一般的な実装に転送します。

テストされていない試み:

def method_missing(method_name, *args)
  super(method_name, *args) unless watched_attributes.include?(method_name)
  attr = ":@#{method_name.to_str}"
  log.debug "Calling watched attribute #{attr}"
  val = instance_variable_get(method_name)
  log.debug "#{attr} was nil omg!" unless val
  val
end
于 2012-06-10T20:05:18.297 に答える
1

あなたが望むのはちょっと混乱です。

このタスクの適切な方法は次のとおりです。

@foo && @foo.downcase

または、Rails ライブラリを使用することもできます。

require 'active_support'

@foo.try(:downcase)
于 2012-06-10T18:26:42.313 に答える
1

現在、これを行う方法はありません。

変数は単なる参照であり、オブジェクト自体ではありません。のようにドット表記を使用してメソッドを呼び出す場合downcase、そのメソッドは変数ではなくオブジェクトに対して動作します。そして、あなたの例のオブジェクトは singletonnilです。あるnil場所で、割り当てられた変数を指定するプロパティが割り当てられている場合、その同じプロパティがすべてnilの に適用されます。

さらに一般的には、1 つのオブジェクトがそれを指す多くの変数/参照を持つ場合があるため、どの変数名をオブジェクトに保存するかを決定する良い方法はありません。ただし、クラスを定数に割り当てる場合、Ruby にはある種の特別な処理があります。その場合、クラス オブジェクトは割り当てられた最初の定数の名前を覚えています。

$ irb
1.9.3p194 :001 > Foo = Class.new do
1.9.3p194 :002 >   attr_accessor :foo
1.9.3p194 :003?> end
 => Foo 
1.9.3p194 :004 > Bar = Foo
 => Foo 
1.9.3p194 :005 > Foo.name
 => "Foo" 
1.9.3p194 :006 > Bar.name
 => "Foo" 
于 2012-06-10T19:58:56.290 に答える
0

編集: おそらく最善の方法(muのコメントを参照)は、文字列を操作していることを確認することです:

@foo.to_s.downcase

これを行うために「名前」を取得する必要はありません。条件を使用できます:

# Downcased if @foo's a string, empty string otherwise:
(String === @foo)? @foo.downcase : ''

または、多くの場所でこれを行う予定で、それぞれを条件付きのモンキー パッチでラップしてNilClassダミーdowncaseメソッドを追加する必要がない場合は、次のようにします。

class NilClass
    def downcase
        return ''
    end
end

それが役立つことを願っています!

于 2012-06-10T18:26:06.613 に答える