RUBY · STEP 1 · INTRO

Ruby · Intro to the language

Ruby 4.0 (any 3.2+ works): variables, input, conditionals, loops, arrays, hashes and methods — each shown first in the JavaScript you know, then in Ruby.

Step 1 of 5Rails© Arthur Bernier Jrrewritten · verified16 code blocks662 words

What you will learn#

  • Creating Variables in a New Language
  • Conditionals in a New Language
  • Looping in a New Language
  • Collections in a New Language
  • Writing Functions in a New Language

Getting Started#

Install the current Ruby from ruby-lang.org/en/downloads (4.0 as of this writing; anything from 3.2 up runs everything on this page and is what Rails 8.1 requires). Most people install it through a version manager — the Install Ruby on Rails guide walks through that on macOS, Ubuntu and Windows (WSL). Then open a terminal:

SH
ruby --versionirb

irb is Ruby's REPL: type an expression, press Enter, see the result; exit leaves. To run a file: ruby hello.rb.

Creating Variables#

How we did it in Javascript

JS
// We create constant variables with the const keywordconst myConstant = 5// We create re-assignable variables with the let keywordlet myVariable = "Hello World" // We print variables to the console using console.logconsole.log(myConstant)console.log(myVariable)

How we do this in Ruby

RB
# A name that starts with a capital letter is a constant. Ruby warns you if you reassign it# (it does not stop you); the convention for values is SCREAMING_SNAKE_CASEMY_CONSTANT = 5# Everything else is a plain variable and re-assignable; snake_case is the normmy_variable = "Hello World" # puts prints a value followed by a newline; parentheses are optional, puts(MY_CONSTANT) is the same callputs MY_CONSTANT# p prints the value's "inspect" form (strings keep their quotes) and returns it; handy for debuggingp my_variable

Receiving Input#

In the browser, input comes from forms or prompt. In Node, reading from the terminal goes through the readline module:

JS
// Node: ask a question in the terminal and wait for the answerimport readline from "node:readline/promises"import { stdin as input, stdout as output } from "node:process" const rl = readline.createInterface({ input, output })const name = await rl.question("Who are you? ")console.log(`Hey there ${name}!`)rl.close()

How would we do that in Ruby?

RB
# puts prints the question; gets reads one line from the terminal, including the newline the Enter key addsputs "Who are you?"user_input = gets.chomp # chomp removes that trailing newline # #{} interpolates any Ruby expression into a double-quoted stringputs "Hey there #{user_input}!"

gets always returns a string (gets.chomp.to_i for a number), and interpolation only works inside double quotes.

Conditionals#

If statements in Javascript

JS
const num = 5 if (num > 3){    console.log("num is greater than 3")} else if (num > 1){    console.log("num is greater than 1")} else {    console.log("num is 1 or less")}

If statements in Ruby

RB
num = 5 # No parentheses or braces: the condition ends the line, and one `end` closes the whole ifif num > 3  puts "num is greater than 3"elsif num > 1  puts "num is greater than 1"else  puts "num is 1 or less"end

Things to know: the middle branch is spelled elsif; &&, ||, ! work as in JavaScript; == never coerces types, so there is no === to reach for; and only nil and false are falsy — 0 and "" are truthy. You'll also see unless (an inverted if) and the one-line form puts "big" if num > 3.

While Loops#

In Javascript

JS
let counter = 0 //This will loop 10 timeswhile(counter < 10){    console.log(counter)    counter += 1}

In Ruby

RB
counter = 0 # this will loop 10 times (Ruby has no ++, use += 1)while counter < 10  puts counter  counter += 1end

while is rare in day-to-day Ruby. You will mostly loop by handing a block ({ } or do ... end) to a method, which calls it once per item:

RB
10.times { |counter| puts counter }   # 0 to 9[1, 2, 3].each { |item| puts item }

10 Minute Exercise#

Write the code to do the following:

  • Loop 10 times starting the counter at 0
  • On each loop if the counter is even print "it's even"
  • If odd, print "meow" if the number is divisible by 3
  • Otherwise print nothing

Collections#

In Javascript we have arrays and objects

JS
const myArray = [1,2,3] console.log(myArray) //logging the entire arrayconsole.log(myArray[0]) // logging an individual item const myObject = {    cheese: "gouda",    bread: "rye"} console.log(myObject) //logging the entire objectconsole.log(myObject.cheese) // logging a property using dot notationconsole.log(myObject["bread"]) // logging a property using square bracket notation

In Ruby you have arrays and hashes

RB
my_array = [1, 2, 3]puts my_array       # puts prints each element on its own linep my_array          # p shows the array the way you would type it: [1, 2, 3]p my_array[0]       # an individual itemp my_array[-1]      # negative indexes count from the end my_hash = { cheese: "gouda", bread: "rye" }p my_hash           # {cheese: "gouda", bread: "rye"}p my_hash[:cheese]  # one value, looked up by its keyp my_hash[:jam]     # a missing key gives nil, not an error

:cheese is a symbol — a lightweight, immutable name Ruby uses for identifiers; cheese: inside { } is shorthand for :cheese =>. The classic gotcha: my_hash["cheese"] is a different key from my_hash[:cheese] and returns nil. There is no dot access for hash keys.

10 Minute Exercise#

Look up Ruby's Array methods and apply them to the following list.

RB
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
  • How to find an array's length (length / size)
  • How to loop over an array (each, each_with_index, map)
  • How to add and remove items from an array (push or <<, pop, unshift, shift, delete, delete_at)

Functions#

in Javascript

JS
const addNums = (x, y) => {    return x + y} console.log(addNums(5,5))

In Ruby

RB
# def ... end defines a method; the value of the last expression is returned automaticallydef add_nums(x, y)  x + yend puts add_nums(5, 5)

return exists, but Ruby only writes it to leave a method early; the last line is the return value. Keyword arguments with defaults are built in:

RB
def greet(name, greeting: "Hello")  "#{greeting}, #{name}!"end puts greet("Arthur")                      # Hello, Arthur!puts greet("Arthur", greeting: "Welcome") # Welcome, Arthur!

The closest thing to an arrow function is a lambda, add = ->(x, y) { x + y }, called with add.call(5, 5); mostly you'll meet anonymous functions as the blocks passed to each, map and select.

10 minute exercise#

Write the following functions

  • sub_nums that takes two arguments and returns their difference
  • say_hello that takes a name as an argument and says hello to that name
  • say_hello_adv that takes a hash with name and age keys and prints "hello {name}, how does it feel to be {age} years old"
  • looper takes one array as an argument, loops over the array and prints each item individually

Resources to Learn More#

  • Control expressions — if/elsif/unless, while, case and the modifier forms, from the official syntax reference
  • Methods — def, default values, keyword arguments, blocks
  • Kernel — puts, p, print, gets and the other methods available everywhere
  • Array and Hash — the methods the exercises ask you to find
  • Official Ruby documentation — the index of everything above, plus Ruby's own tutorials

See also