Tuesday, 11 February 2014

Ruby - Constants

The main aspect to remember about Constants in Ruby, is that their values are meant to be set when they’re initialised and then remain constant for as long as the script remains held in memory. The Ruby interpreter doesn’t enforce this however, so it is possible to change the value of a Constant. The interpreter will throw an error and it’s considered bad practice, so the advice is - don’t do it. If you are likely to want to change the value of a Constant, then consider the use of other types of variables.


In the previous post about Ruby Global Variables, it was suggested they could be used to hold a constant value while the script was running. However, in our example we used a Global variable to leave open the option that the opening Hero Name might be assigned by the player. There’s nothing stopping you using a variable of one type or another and keeping the value constant during the life of your programme or going ahead and using a Constant. Just make sure you set it up properly and that others reading your code will know your intentions.

Type the following into a new .rb file and run it via a CMD window
#Test of assigning and then reassigning a value to a Constant


puts "Value of the First Constant is: #{FIRST_CONST}"
puts "Value of the Second Constant is: #{SECOND_CONST}"

puts "Now we'll change the value of the First Constant"

# We should see a warning message now, but the value will be changed
puts "Value of the First Constant has been changed: #{FIRST_CONST}"

If you try to use an uninitialized Constant, you’ll get a NameError exception thrown.
Type the  following into a new .rb and run it via a CMD window.

# Testing for the NameError exception on an unititilised Constant
puts "Here's what happens if the Constant hasn't been initialised"
puts "#{DOES_NOT_EXIST}"

Also, try the following to show that a Constant doesn’t exist if it has no value assigned.

# Showing a Constant doesn't exist if it's had no value assigned
puts "Does a Constant with no value exist?"

Naming Constants
Constants must begin with an upper case letter, for example Inventory. From the previous post on Instance and Class variable, you’ll perhaps realise via this naming convention, that every Class and Module name creates a Constant. However, they are usually written using Camel Case which helps differentiate them from Constants, e.g. InventoryCheck.

To help keep a differentiation between Class and Constant names there are two common conventions for their naming:
  • Using all uppercase letters, e.g. INVENTOR
  • Combining with underscores if needed, eg. MY_INVENTORY

Scope of Constants
As with our Local, Global, Instance and Class variables, there are some scope rules to bear in mind when using Constants within your Ruby scripts:
·         Constants can’t be defined in Methods (dynamic assignment error, see below)
·         Constants defined in the main body of the script can be accessed globally
·         Constants defined within a Class or Module can only be accessed from within those Classes or Modules

Try the following in a new .rb file and see what happens with accessing a Constant within a Class

# accessingConstants_001.rb
# This re-uses the Class called Creature that we saw in earlier posts

# We'll create a Constant outside any Class, Method, etc. to see if it's Globally accessible
MOB_INVENTORY = "The creature's Inventory is empty right now.\n"

class Creature
  @@mobType = "NPC"
  MOB_WEAPON = "The Mob's weapon is a Club"

        def initialize creatureName
            @name = creatureName
          end #def initialize creatureName

        def to_s
            "Creature name is #{@name}. It is an #{@@mobType}.\n"
          end # def to_s

        def inventory
         puts "Called from within the Class: #{MOB_INVENTORY}"

        def mob_weapon
         puts "Called from & defined within the Class: #{MOB_WEAPON}"

end #Creature class

# Create a new instance of the Creature class, then assign it a name via the @name Instance variable
mob_001 = Creature.new "Silver Kobold"

# Access the Constant directly, as it's declared in the body of the script
puts "Called from main body: #{MOB_INVENTORY}"

# Access the MOB_INVENTORY Constant via the CLASS, showing it has Global scope as the Class can reach it

# Access the MOB_WEAPON Constant defined within the CLASS itself

As described in the comments we can see three things in action:
  • Use of the Constant MOB_INVENTORY via a Class, showing its Global scope
  • Access the Constant MOB_INVENTORY directly outside any Class or Module
  • Access the MOB_WEAPON Constant, defined in a Class, via the Class

For a final test, try the following code in a new .rb file


def mobSpell
        MOB_SPELL = puts "A Constant defined in a Method"

As we’ll see, this fails with a ‘dynamic constant assignment’ error. The issue here is instead of assigning a static value, we’re trying to dynamically assign it each time the Method is used.

That concludes our overview of Ruby variables; Local, Global, Instance and Class, along with our look at Constants, which we might also find use for when creating our scripts.

Next up, we’ll look at Ruby Arrays, a great way to store and work with sets of data. Taking us beyond the variable and its single piece of data.



Read More