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によって実装されていると述べたように、ここには少し魔法があります。

したがって、実際には、メソッドのオプションが定義されることを期待してはいけませんbaz

于 2013-03-05T08:16:56.990 に答える
1

これは#bar、実際の on のメソッドではなく、inRails::Engine::configを介して実装されているためです。それが実際のメソッド ( で実装されている)である場合は、が返されます。#method_missingRails::Railtie::Configurationdef 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

そして、質問の2番目の部分に対処するために、構成オプションが通常見えるインスタンス変数ではなく、クラス変数に格納されているため、#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 に答える