Different variables behave differently in Ruby, but none of them need explicit declaration.
The most interesting behavior is for local variables: Ruby allows you to leave off the receiver for a message send to self (self is the implicit receiver), so foo() is the same thing as self.foo(), and it also allows you to leave off the argument list if there are no arguments, so foo.bar is the same thing as foo.bar(); putting the two together, we get that foo is the same thing as self.foo(), i.e. a message send without arguments to the implicit receiver self. It could, however, also be a reference to the local variable foo. This ambiguity is resolved the following way: foo is interpreted as a message send, unless an assignment to foo has been parsed (but not necessarily executed) before, then from that point on it is interpreted as a local variable.
This is the closest thing Ruby has to variable declaration:
foo
# NameError: undefined local variable or method `foo'
defined?(foo)
# => nil
def foo; 23 end
foo
# => 23
defined?(foo)
# => 'method'
methods
# => [:foo, …]
if false then foo = 42 end
foo
# => nil
defined?(foo)
# => 'local-variable'
local_variables
# => [:foo]
Note that the NameError is not raised because the local variable is undefined, but because Ruby doesn't know what to make of the expression: is it a local variable or a method call?
Instance variables and global variables behave similarly, they evaluate to nil even if they are not defined:
@foo
# => nil
defined?(@foo)
# => nil
@foo = 42
@foo
# => 42
defined?(@foo)
# => 'instance-variable'
instance_variables
# => [:@foo]
$foo
# => nil
defined?($foo)
# => nil
$foo = 42
$foo
# => 42
defined?($foo)
# => 'global-variable'
global_variables
# => [:$foo, …]
Class hierarchy variables and constants behave differently, they raise NameError if they are not defined:
@@foo
# NameError
defined?(@@foo)
# => nil
@@foo = 42
@@foo
# => 42
defined?(@@foo)
# => 'class-variable'
self.class.class_variables
# => [:@@foo]
FOO
# NameError
defined?(FOO)
# => nil
FOO = 42
FOO
# => 42
defined?(FOO)
# => 'constant'
self.class.constants
# => [:FOO]
NameErrorif they are not defined, instance variables and global variables evaluate tonil, and local variables also evaluate tonilbut need to be disambiguated from a method call by being lexically defined first, otherwise they will raise aNameErrorbut for being ambiguous, not undefined. – Jörg W Mittag Jan 12 '15 at 23:17