Ruby中Self的变量名

时间:2012-06-10 18:14:04

标签: ruby

我有一个变量,可以调用它@foo。我希望它是一个字符串,所以我打电话给@foo.downcase。有时它是零,我会得到这个错误:

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>

要做这样的事情,我需要以编程方式获取变量的名称。

问题:是否有可能以编程方式获取变量的名称?

我正在寻找能产生如下输出的东西:

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

我不想要变量的值,也不关心它是nil。我想要变量的人类可读名称。是否有可能以编程方式获取变量的名称?

4 个答案:

答案 0 :(得分:1)

你想要的是有点混乱。

这是执行此任务的正确方法:

@foo && @foo.downcase

或者你可以使用rails library:

require 'active_support'

@foo.try(:downcase)

答案 1 :(得分:1)

目前没有办法做到这一点。

变量只是引用,而不是对象本身。如果使用点表示法来调用方法(如downcase),则该方法对对象而不是变量进行操作。你的例子中的对象是单身nil;如果nil在一个地方分配了一个属性来命名它所分配的变量,那么同一属性将适用于所有nil

更一般地说,一个对象可能有许多指向它的变量/引用,因此没有好的方法来确定应该在对象中保存哪个变量名。 然而,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" 

答案 2 :(得分:1)

您可以使用instance_variable_get(:@ foo)从符号中获取实例变量 这只会给你价值。

但你可以这样做:

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

您还可以为想要观看的attrs执行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

答案 3 :(得分: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

希望有所帮助!