Reputation: 12273
I have an initializer for an engine named Foo
like so:
# config/initializer/foo.rb
class Foo::Engine < ::Rails::Engine
config.bar = 'baz'
end
But it behaves in unexpected ways:
Foo::Engine.config.bar # => 'baz' # expected
defined?(Foo::Engine.config.bar) # => nil, why?
Why is defined?
nil?
Also, when I do Foo::Engine.config.inspect
many things show up but bar
is nowhere to be found. Why?
Upvotes: 0
Views: 109
Reputation: 11588
It is because #bar
is not a real method on Rails::Engine::config
but is implemented via #method_missing
in Rails::Railtie::Configuration
. If it were a real method (implemented with def bar
) defined?
would return "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
And to address the second part of your question, #inspect
does not include bar
is because the configuration options are stored in the @@options
class variable, not in an instance variable where #inspect
normally looks:
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
Upvotes: 1
Reputation: 23344
As stated in the Expressions @ Programming Ruby,
The defined?
operator returns nil
if its argument (which can be an arbitrary expression) is not defined, otherwise it returns a description of that argument.
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"
So for classes:
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"
For methods:
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"
In your case,
defined?(options)
is calling the options method and passing the result to defined?
.
Thanks to @Stuart, as mentioned that its not a real method but its implemented by method_missing, there is a little magic here.
So in fact you should not be expecting the method options to be defined therefore getting nil for baz
.
Upvotes: 1