Skip to main content
View
Chapter 1 / 16Variables and data types
1. Variables and data types
2. Strings and symbols
3. Arrays
4. Hashes
5. Conditionals
6. Loops and iterators
7. Methods and blocks
8. Classes and objects
9. Inheritance
10. Modules
11. Extending code with prepend
12. Enumerable
13. Where to go next
14. Error handling
15. Reading and writing files
16. Advanced class features

Variables and data types

This guide is the first in a series of Ruby courses. In this first chapter, we learn how to store information in variables.

No prior programming knowledge is required. We start from scratch.

Prerequisites

Before starting, Ruby and a code editor must be installed on your machine. If this is not yet done, follow the guide "How to set up your development environment" in the Miscellaneous section of the tutorials.

Testing code with IRB

Throughout this chapter, we will write small bits of code to understand each concept. The quickest way to test Ruby is to use IRB (Interactive Ruby). It is a console that executes Ruby line by line and immediately displays the result.

To launch IRB, open a terminal (in VSCode: menu Terminal > New Terminal) and type:

irb

You get a prompt irb(main):001:0> where you can type Ruby:

irb(main):001:0> 1 + 1
=> 2
irb(main):002:0> 'Pikachu'.length
=> 7
  • Each line is executed immediately. The result is displayed after =>.
  • To quit IRB, type exit.
  • IRB is perfect for testing a quick operation, checking a behavior, or experimenting. We will use it a lot in the first chapters.

Principle

A program manipulates data: a name, a number, a list. To use this data, it needs to be stored somewhere. That is the role of a variable: a name that points to a value.

You can think of a variable as a label stuck on a box. The label (the name) lets you find what the box contains (the value). At any time, you can change the contents of the box without changing the label.

Creating a variable

In Ruby, creating a variable is as simple as writing a name, the = sign, then the value you want to store:

name = 'Pikachu'
level = 25
  • name is the variable name. We chose this name; it could be anything else.
  • = is the assignment operator. It says "the variable on the left now contains the value on the right".
  • 'Pikachu' is the value we store: here, text (called a character string or String).
  • level stores an integer (Integer).

We can then use these variables anywhere we would have used the value directly:

name = 'Pikachu'
level = 25

puts name # Displays: Pikachu
puts level # Displays: 25
  • puts is a command that displays a value on screen. It is one of the first tools we use to verify that our code does what we expect.

Changing the value of a variable

You can replace the contents of a variable at any time. The old value is simply forgotten:

name = 'Pikachu'
puts name # Displays: Pikachu

name = 'Eevee'
puts name # Displays: Eevee
  • The variable name first points to 'Pikachu', then to 'Eevee'. The name does not change, only the contents change.

Data types

Not all values are alike. A name is text, a level is a number, a legendary status is true or false. Ruby distinguishes these different data types. Let's look at the main ones.

Integers (Integer)

An Integer is a number without a decimal point. It is used for levels, Pokedex numbers, hit points:

pokedex_number = 25
level = 50
max_team_size = 6

For large numbers, Ruby allows underscores _ to make reading easier. The program ignores them completely:

# These two lines are identical for Ruby
experience = 1000000
experience = 1_000_000

Decimal numbers (Float)

A Float is a number with a decimal point:

damage_multiplier = 1.5
capture_rate = 0.75
  • Floats are used when decimal precision is needed, such as damage multipliers.

Text (String)

A String is a sequence of characters surrounded by quotes. Ruby accepts single quotes '...' or double quotes "...":

pokemon_name = 'Pikachu'
description = "An adorable Electric-type Pokémon"

The difference between the two is important. Double quotes allow you to insert variables into text using the #{} syntax. This is called interpolation:

name = 'Pikachu'
level = 25

# With double quotes: interpolation works
puts "#{name} is level #{level}" # Displays: Pikachu is level 25

# With single quotes: interpolation does NOT work
puts '#{name} is level #{level}' # Displays: #{name} is level #{level}
  • Interpolation is very handy for building sentences from variables. We will use it constantly.
  • Simple rule: if the text contains variables, use double quotes. Otherwise, single quotes are fine.

Symbols (Symbol)

A Symbol looks like a String, but it starts with : and has no quotes:

pokemon_type = :electric
status = :healthy

What is the difference from a String? A Symbol is a fixed identifier. You never modify it; you compare it. It is like a label carved in stone, while a String is text that can be rewritten.

In practice:

  • Use a Symbol when the value is an identifier: a Pokemon type (:fire, :water), a status (:poisoned), a nature (:adamant).
  • Use a String when the value is text displayed to the user: a name, a description, a message.
# Symbol -- an identifier, always the same
pokemon_type = :electric

# String -- text intended for display
pokemon_name = 'Pikachu'

Booleans (true / false)

A boolean represents a value that is either true (true) or false (false). It is used for questions whose answer is yes or no:

is_legendary = false
is_alive = true
has_mega_evolution = true
  • There is no Boolean class in Ruby. true is of type TrueClass and false is of type FalseClass. This is a quirk of the language; no need to remember it for now.

The absence of value (nil)

Sometimes a variable simply has no value. In Ruby, nil is used to say "nothing", "empty", "not defined":

held_item = nil
secondary_type = nil
  • nil is not zero, nor an empty string. It is the total absence of value.
  • A single-type Pokemon has no secondary type. nil expresses exactly this idea.

Knowing the type of a value

Ruby allows you to ask any value what its type is. Two tools are useful for this:

puts 'Pikachu'.class # => String
puts 25.class # => Integer
puts 1.5.class # => Float
puts :electric.class # => Symbol
puts true.class # => TrueClass
puts nil.class # => NilClass
  • .class asks a value "what type are you?".

You can also ask the question differently: "are you of this type?":

puts 25.is_a?(Integer) # => true
puts 25.is_a?(Float) # => false
puts 'Pikachu'.is_a?(String) # => true
  • .is_a? answers with true or false. The ? at the end of the name is a Ruby convention: methods that ask a question end with ?.

Displaying and debugging

We saw puts for displaying. There is a second very useful tool: p.

name = 'Pikachu'
types = [:electric]

puts name # => Pikachu (clean display, for the user)
p name # => "Pikachu" (technical display, for the developer)

puts types # => electric (displays each element on a line)
p types # => [:electric] (shows the complete structure)

puts nil # => (displays an empty line)
p nil # => nil (displays the word nil)
  • puts displays the value in a readable way. It is what we use for messages intended for the user.
  • p displays the value in a technical way, with quotes, brackets, etc. It is what we use when we want to understand exactly what a variable contains. It is a debug tool.

Compound assignment operators

We often need to modify a variable based on its current value. For example, increasing experience by 100 points. We could write:

experience = 0
experience = experience + 100
puts experience # => 100

Ruby offers a shortcut with +=:

experience = 0
experience += 100 # Equivalent to: experience = experience + 100
puts experience # => 100

Here are the main shortcuts:

experience = 100
experience += 50 # addition => 150
experience -= 20 # subtraction => 130
experience *= 2 # multiplication => 260
experience /= 4 # division => 65
experience %= 10 # modulo (remainder of division) => 5
  • += is by far the most common. The others are useful but less frequent.
  • The modulo (%) returns the remainder of a division. 10 % 3 gives 1 because 10 divided by 3 is 3 remainder 1.

Naming your variables

In Ruby, variable names follow a convention called snake_case: all lowercase, words separated by underscores:

# Good names
pokemon_name = 'Pikachu'
max_health_points = 142
is_legendary = false

# Bad names -- avoid these
pokemonName = 'Pikachu' # this is camelCase, not used in Ruby
n = 'Pikachu' # too short, impossible to understand
x = 142 # same problem
  • A good variable name describes what it contains. Anyone reading the code should understand without effort what each variable represents.
  • Never abbreviate: pokemon_name and never pkmn_name or pn.

Constants

Some values never change during program execution. The maximum number of Pokemon in a team is always 6. They are defined as constants, in uppercase:

MAX_TEAM_SIZE = 6
POKEDEX_VERSION = '0.1.0'
TYPE_FIRE = :fire
  • Constants use SCREAMING_SNAKE_CASE: all uppercase, separated by underscores.
  • Ruby displays a warning if you modify a constant, but does not prevent it. It is a convention, not a technical restriction.

Conclusion

  • A variable is a name that points to a value. It is created with =.
  • Ruby has 6 fundamental types: Integer (whole number), Float (decimal number), String (text), Symbol (identifier), Boolean (true/false), and nil (absence of value).
  • Symbols serve as identifiers (:fire, :water). Strings serve for displayed text.
  • Interpolation ("#{variable}") inserts a variable into text. It only works with double quotes.
  • puts displays for the user, p displays for debugging.
  • Variable names use snake_case. Constants use SCREAMING_SNAKE_CASE.
  • .class gives the type of a value. .is_a? checks whether a value is of a certain type.