Variables can contain any object in Ruby; you can readily assign a string to a variable that previously held an integer. Variable names must begin with a lower-case letter or underscore (after the prefix). By convention, they are all lower-case, with words separated by underscores (eg my_variable).
Local Variables
Local variables have no prefix. They exist only within a block of code, such as a method. Once the block completes, the variable disappears.
def test2
local1 = 2
local1.times do
local2 = 3
p "l1=#{local1} l2=#{local2}"
end
p "l1=#{local1}"
#p "l2=#{local2}" # Out of scope
end
Instance Variables
An instance variable belongs to that one instance of the class. It is denoted by a single at symbol (eg
@var
), and can be accessed from any instance of a class from within a method. They have private access... however, you can access them anyway through these methods:instance_variables # Array of strings, listing instance variables
instance_variable_defined?
instance_variable_set
instance_variable_get
remove_instance_variable # Private method
You can also use
attr_accessor
, attr_reader
and attr_writer
to allow others to access your instance variables. Note that while the above methods do require the at sign, these three methods do not.You can also access instance variables using self. These two statements are equivalent.
self.var = 19
@var = 19
Class Variables
A class variable belongs to the whole class (and indeed subclasses), and is accessible from anywhere inside the class, or from any instance of the class. If you change the value in one instance, it will be changed in every instance. It must start with two at symbols (eg
@@var
).In Rails, you can access a class variable like a class method (eg
MyClass.var
) for a descendant of ActiveRecord::Base
(analogous to how you access column names). Outside Rails class variables have private access.Class variables have some perhaps surprising behavior when you look at inheritance, as a value set in a subclass can affect other classes. Let us see that in action.
SubClass1
has a parent, SuperClass
, a sibling, SubClass2
, and a child SubSubClass1
.class SuperClass
@@var1 = 11
@@var2 = 21
def self.out1; @@var1; end
def self.out2; @@var2; end
end
class SubClass1 < var1 =" 12" var3 =" 31" var1 =" 13" var3 =" 32" var2 =" 22"> 13
p SubClass1.out1
# => 13
p SubClass2.out1
# => 13
# @var2 is in the top class and its grandchild class. Despite "skipping
# a generation", the value set in the sub-sub-class still affects the
# super-class
p SuperClass.out2
# => 22
p SubSubClass1.out2
# => 22
# @var3 is in the sibling classes only, not in a common super-class. In this
# case setting the value in one has no effect on the other.
p SubClass1.out3
# => 31
p SubClass2.out3
# => 32
There are a set of methods available to use class variables, analogous to those for instance variables.
class_variables # Array of strings, listing instance variables
class_variable_defined?
class_variable_set
class_variable_get
remove_class_variable # Private method
In Rails, you can define setters and getters just as you can for instance variables;
cattr_accessor
, cattr_reader
and cattr_writer
.Global Variables
A global variable must start with a dollar (eg
$var
). It accessible from any class at any time. They are generally regarded as something to avoid; better to keep sections of code isolated from each other as far as possible.Ruby has a number of predefined global variables. I do not like to use them myself; they make code that much harder to understand, and where there is a more explicit alternative, I would always use that. However, there is a list here.
There is an interesting trace feature for global variables. The
trace_var
method takes either a string or a symbol representing the global variable (with the dollar sign), together with a proc
object (the documentation claims it will take a string or block as well; I do not believe that that is true).trace_var "$global_var", proc do |x|
puts "$global_var is now #{x}"
end
You can set more than one trace on a global variable, and you can remove them (all) with
untrace_var
.The
global_variables
method will return an array of strings, the names of all the global variables (complete with dollar sign).Special Variables
Ruby includes a handful of special variables:
self # "this" in Java, etc.
true
false
nil # "null" in Java, etc., also counts as false
__FILE__ # the current file
__LINE__ # the current line number.
All Together Now
Let us them all in action. Here is some sample code.
$global_var = 32
class TestClass
@@class_var = 14
def initialize
@instance_var = 20
end
def test
local_var = 7
$global_var += 1
@@class_var += 1
@instance_var += 1
local_var += 1
puts "$global_var=#{$global_var}"
puts "@@class_var=#{@@class_var}"
puts "@instance_var=#{@instance_var}"
puts "local_var=#{local_var}"
end
end
Both
$global_var
and @@class_var
are set when the file is loaded. While $global_var
is available to everything, @@class_var
can only be accessed from within TestClass
. Looking at @instance_var
, this will be set to 20 for a specific instance of TestClass
when the instance is created. It will be incremented whenever test is invoked on that instance, in contrast to $global_var
and @@class_var
, both of which will get incremented every time test is invoked on any instance. Finally, local_var
is created when it is set in the test method, and destroyed when the method terminates.Struggling with Ruby: Contents Page