Menu
Coddy logo textTech

Constants

Part of the Object Oriented Programming section of Coddy's Ruby journey. Lesson 14 of 57.

A constant starts with a capital letter and by convention is written in capitals. Defined in a class body, it can be used by name in every method of the class. Outside the class you write ClassName::NAME:

class Account
  MIN_BALANCE = -100

  def self.allowed?(balance)
    balance >= MIN_BALANCE
  end
end

puts Account::MIN_BALANCE
puts Account.allowed?(-50)
puts Account.allowed?(-150)

Output:

-100
true
false

Constants suit fixed data that the whole class uses, such as limits or lookup tables. fetch on a hash constant raises KeyError for an unknown key instead of quietly returning nil:

class Shipping
  RATES = { "standard" => 5, "express" => 12 }.freeze

  def self.cost(method)
    RATES.fetch(method)
  end
end

puts Shipping.cost("express")
begin
  Shipping.cost("drone")
rescue KeyError => e
  puts e.message
end

Output:

12
key not found: "drone"

A constant name cannot be pointed at a new object without Ruby printing a warning, but the object it holds can still be changed. freeze makes the object itself read-only, so a change raises FrozenError:

class Palette
  COLORS = ["red", "green"].freeze
end

begin
  Palette::COLORS << "blue"
rescue FrozenError => e
  puts e.message
end
p Palette::COLORS
p Palette::COLORS.frozen?

Output:

can't modify frozen Array: ["red", "green"]
["red", "green"]
true

Choose by how the value behaves. A value that never changes belongs in a frozen constant; state that changes while the program runs, such as a counter, belongs in a class instance variable:

class Ticket
  PREFIX = "TK"                  # fixed: a constant
  @issued = 0                    # changes: class instance variable

  def self.next_code
    @issued += 1
    "#{PREFIX}-#{@issued}"
  end
end
challenge icon

Challenge

Easy

Complete the class Order. It has the constants RATES (a frozen hash: standard costs 5, express 12, pickup 0) and FREE_FROM (50). initialize(total, method) raises ArgumentError with unknown shipping: drone when the method is not a key of RATES. shipping returns 0 for totals from FREE_FROM upwards and the rate otherwise, and to_s returns 40.00 + 5 express = 45.00.

The supplied code prints free from 50 using the constant, then reads orders as total method lines and prints each order or the error message.

Your code goes in order.rb. main.rb holds the supplied input/output code and cannot be edited.

Try it yourself

require_relative 'order'

# Supplied input/output code: keep it as it is
input = []
while (line = gets)
  input << line.chomp
end
puts "free from #{Order::FREE_FROM}"
input.each do |line|
  total, method = line.split
  begin
    puts Order.new(total.to_f, method)
  rescue ArgumentError => e
    puts e.message
  end
end
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Object Oriented Programming

Practice on your own: Online Ruby compiler