0

我有一个这样命名的引擎的初始化程序Foo

# config/initializer/foo.rb
class Foo::Engine < ::Rails::Engine
  config.bar = 'baz'
end

但它以意想不到的方式表现:

Foo::Engine.config.bar # => 'baz' # expected
defined?(Foo::Engine.config.bar) # => nil, why?

为什么是defined?零?

另外,当我做Foo::Engine.config.inspect很多事情时,会出现但bar无处可寻。为什么?

4

2 回答 2

1

Expressions@Programming Ruby中所述,

如果未定义其参数(可以是任意表达式),则运算符返回,否则返回该参数的描述defined?nil

defined? 1 → "expression"
defined? dummy → nil
defined? printf → "method"
defined? String → "constant"
defined? $& → nil
defined? $_ → "global-variable"
defined? Math::PI → "constant"
defined? ( c,d = 1,2 ) → "assignment"
defined? 42.abs → "method"

所以对于类:

ruby-1.9.2-p180 > defined? Person

 => nil

ruby-1.9.2-p180 > class Person

ruby-1.9.2-p180 ?>  end

 => nil

ruby-1.9.2-p180 > defined? Person

 => "constant"

对于方法:

ruby-1.9.2-p180 > def cool

ruby-1.9.2-p180 ?>  puts "clear"

ruby-1.9.2-p180 ?>  end

 => nil

ruby-1.9.2-p180 > defined? cool

 => "method"

在你的情况下

defined?(options)正在调用 options 方法并将结果传递给defined?.

感谢@Stuart,如前所述,它不是真正的方法,而是由method_missing实现的,这里有一点魔力。

所以实际上你不应该期望方法选项被定义,因此得到 nil baz

于 2013-03-05T08:16:56.990 回答
1

这是因为#bar不是真正的方法 onRails::Engine::config而是通过#method_missingin实现的Rails::Railtie::Configuration。如果它是一个真正的方法(用 实现def bardefined?将返回"method"

class Foo
  def bar
    'bar'
  end

  def method_missing(name, *args, &blk)
    if name == :baz
      'baz'
    end
  end
end

f = Foo.new
f.bar           # => "bar"
defined?(f.bar) # => "method"
f.baz           # => "baz"
defined?(f.baz) # => nil

为了解决您问题的第二部分,#inspect不包括bar是因为配置选项存储在@@options类变量中,而不是#inspect通常看起来的实例变量中:

def method_missing(name, *args, &blk)
  if name.to_s =~ /=$/
    @@options[$`.to_sym] = args.first
  elsif @@options.key?(name)
    @@options[name]
  else
    super
  end
end
于 2013-03-05T08:37:09.503 回答