Ben Wheeler
Ben Wheeler

Reputation: 7384

Rails/Ruby incorrectly showing variable not defined

In debugging console, while app running (using binding.pry to interrupt it), I can see that my variable Rails.configuration.hardcoded_current_user_key is set:

pry(#<TasksController>)> Rails.configuration.hardcoded_current_user_key
=> "dev"

But it doesn't appear to be defined:

pry(#<TasksController>)> defined?(Rails.configuration.hardcoded_current_user_key)
=> nil

Yet it works fine to store and test its value:

pry(#<TasksController>)> tempVar = Rails.configuration.hardcoded_current_user_key
=> "dev"
pry(#<TasksController>)> defined?(tempVar)
=> "local-variable"

What is going on?

Upvotes: 3

Views: 154

Answers (2)

Halil &#214;zg&#252;r
Halil &#214;zg&#252;r

Reputation: 15945

This is because Rails config implements respond_to? but not respond_to_missing?, and defined? only recognizes respond_to_missing?:

class X
  def respond_to?(name, include_all = false)
    name == :another_secret || super
  end

  private

  def method_missing(name, *args, &block)
    case name
    when :super_secret
      'Bingo!'
    when :another_secret
      'Nope.'
    else
      super
    end
  end

  def respond_to_missing?(name, include_all = false)
    name == :super_secret || super
  end
end

x = X.new
puts x.super_secret          # => Bingo!
p defined?(x.super_secret)   # => "method"
puts x.another_secret        # => Nope.
p defined?(x.another_secret) # => nil

It's recommended to implement respond_to_missing? along with method_missing, I too wonder why Rails did it that way.

Upvotes: 4

tadman
tadman

Reputation: 211740

You shouldn't be using defined? on anything but the "stub" of that, or in other words, merely this:

defined?(Rails)

Anything beyond that is highly unusual to see, and I'm not even sure it's valid.

defined? is not a method, but a construct that tests if the following thing is defined as a variable, constant or method, among other things. It won't evaluate your code, it will just test it as-is. This means method calls don't happen, and as such, can't be chained.

If you want to test that something is assigned, then you should use this:

Rails.configuration.hardcoded_current_user_key.nil?

Upvotes: 0

Related Questions