Skip to content

Instantly share code, notes, and snippets.

@Brymes
Created September 6, 2024 02:28
Show Gist options
  • Save Brymes/2bdbaf9ceb80561dcc22fae0990d8b83 to your computer and use it in GitHub Desktop.
Save Brymes/2bdbaf9ceb80561dcc22fae0990d8b83 to your computer and use it in GitHub Desktop.
Ruby Cheat Sheet

Ruby Cheat Sheet (GPT ASSISTED)

Index

  1. Basic Syntax
  2. Operators
  3. Declarations
  4. Functions
  5. Built-in Types
  6. Type Conversions
  7. Modules
  8. Control Structures
  9. Arrays, Hashes, and Ranges
  10. Classes
  11. Blocks and Yield
  12. Symbols
  13. Mixins
  14. Exceptions
  15. Threads
  16. Snippets

Ruby in a Nutshell

  • Imperative, Object-Oriented language
  • Dynamically typed
  • Syntax similar to Python/Perl, with extensive use of blocks and procs
  • Everything is an object, including numbers and classes
  • Rich metaprogramming features
  • Uses modules to share functionality across classes
  • Blocks, Procs, and Lambdas for functional programming
  • Exception handling with begin-rescue
  • Built-in threading with native OS threads

Basic Syntax

Hello World

File hello.rb:

Reserved Keywords

Ruby has a set of reserved keywords that cannot be used as variable names, method names, or any identifiers. These words have specific meanings in the language and are used for control structures, declarations, and other language constructs.

Here’s a list of Ruby's reserved keywords:

__ENCODING__  __LINE__  __FILE__
BEGIN         END       alias
and           begin     break
case          class     def
defined?      do        else
elsif         end       ensure
false         for       if
in            module    next
nil           not       or
redo          rescue    retry
return        self      super
then          true      undef
unless        until     when
while         yield

Notes

  • __ENCODING__, __LINE__, and __FILE__ are special constants that return the encoding of the script, the current line number, and the name of the file, respectively.

  • BEGIN and END are used to define code blocks that run before and after the program's execution.

  • and, **or**, and not are logical operators but behave differently in terms of precedence compared to &&, ||, and !.

These keywords are reserved by the language and should be avoided as custom identifiers in your code.

puts "Hello Ruby"

$ ruby hello.rb

Operators

Arithmetic

Operator Description
+ addition
- subtraction
* multiplication
/ quotient
% remainder
& bitwise and
| bitwise or
^ bitwise xor
<< left shift
>> right shift

Comparison

Operator Description
== equal
!= not equal
< less than
<= less than or equal
> greater than
>= greater than or equal

Logical

Operator Description
&& logical and
|| logical or
! logical not

Other

Operator Description
& address of / create reference
* dereference reference

Declarations

Variables

# Variable declaration and assignment
foo = 42          # no need to declare type, dynamically assigned
foo, bar = 42, 1302  # multiple assignment

# Constants (by convention, constants are written in uppercase)
CONSTANT = "This is a constant"

Constants

# Constants are defined with an uppercase name, and are meant to remain unchanged
MAX_SIZE = 100

Local Variables

# Local variables start with a lowercase letter or an underscore
local_variable = "I'm local"

Global Variables

# Global variables start with a dollar sign ($)
$global_variable = "I'm global"

Instance Variables

# Instance variables start with an '@' sign and are used within classes
@instance_variable = "I'm an instance variable"

Class Variables

# Class variables start with two '@' signs and are shared among all instances of the class
@@class_variable = "I'm a class variable"

Symbols

# Symbols are immutable, reusable constant identifiers, often used as keys or identifiers
:my_symbol

Type Inference

Ruby automatically infers the type based on the assigned value. No need for explicit type declaration.

Functions

# a simple function
def function_name
end

# function with parameters
def function_name(param1, param2)
end

# function with a return type
def function_name
  return 42
end

# return multiple values
def return_multi
  return 42, "foobar"
end
x, str = return_multi

# use default values for parameters
def function_name(param1 = 42, param2 = "foo")
end

# return named results
def return_multi2
  n = 42
  s = "foobar"
  return n, s
end
x, str = return_multi2

Blocks, Procs, and Lambdas

# Blocks
def method_with_block
  yield if block_given?
end

method_with_block { puts "Block executed!" }

# Procs
add = Proc.new { |a, b| a + b }
puts add.call(3, 4)  # Outputs 7

# Lambdas
multiply = ->(a, b) { a * b }
puts multiply.call(3, 4)  # Outputs 12

Variadic Functions

# Ruby supports variadic functions using the splat operator (*)
def adder(*args)
  args.sum
end

puts adder(1, 2, 3)     # Outputs 6
puts adder(9, 9)        # Outputs 18

nums = [10, 20, 30]
puts adder(*nums)       # Outputs 60

Built-in Types

# Numeric types
Integer  # Fixnum and Bignum in older versions of Ruby
Float    # floating-point numbers
Complex  # complex numbers

# Boolean types
TrueClass
FalseClass

# Strings
String

# Symbols
Symbol

# Arrays and Hashes
Array
Hash

# Nil and Other Basic Types
NilClass
Range
## Type Conversions
In Ruby, explicit type conversions are done using methods like `to_i`, `to_f`, `to_s`, etc.

```ruby
# Converting types
i = "42".to_i      # string to integer
f = "42.42".to_f   # string to float
s = 42.to_s        # integer to string
b = 1.to_s == "1"  # integer to boolean-like comparison
  • .to_i - Converts to integer.
  • .to_f - Converts to float.
  • .to_s - Converts to string.
  • .to_sym - Converts to symbol.

Modules

Modules are collections of methods and constants. They can be used as namespaces or mix-ins (to share functionality across classes).

# Defining a module
module MyModule
  MY_CONSTANT = 100

  def my_method
    puts "Hello from MyModule"
  end
end

# Including a module in a class
class MyClass
  include MyModule
end

obj = MyClass.new
obj.my_method      # => "Hello from MyModule"
  • Modules are not instantiable.
  • They can be mixed into classes via include (for instance methods) or extend (for class methods).

Control Structures

If

Ruby uses if, elsif, and else for conditional control.

x = 10

if x > 0
  puts "x is positive"
elsif x < 0
  puts "x is negative"
else
  puts "x is zero"
end

# Single-line if modifier
puts "x is positive" if x > 0

Loops

Ruby supports several ways to loop, including while, until, for, and iterators like each.

# while loop
i = 0
while i < 5 do
  puts i
  i += 1
end

# until loop
i = 5
until i == 0 do
  puts i
  i -= 1
end

# for loop
for i in 1..5 do
  puts i
end

# Using an iterator
(1..5).each do |i|
  puts i
end

Case

The case statement in Ruby works like a switch in other languages.

fruit = "apple"

case fruit
when "apple"
  puts "This is an apple"
when "banana"
  puts "This is a banana"
else
  puts "Unknown fruit"
end

# You can also use ranges and regular expressions in case
age = 25
case age
when 0..17
  puts "You're a minor"
when 18..64
  puts "You're an adult"
else
  puts "You're a senior"
end
  • The case statement compares the object against each when condition, executing the first matching one.
## Arrays, Hashes, and Ranges

### Arrays
An array in Ruby is an ordered collection of elements, which can be of any type. Arrays are indexed starting from 0.

```ruby
arr = [1, 2, 3, "four", 5.0]
puts arr[0]         # => 1
puts arr[-1]        # => 5.0 (last element)
puts arr[1..3]      # => [2, 3, "four"] (range of elements)
  • Arrays are dynamic, meaning you can add or remove elements easily.
  • Use push, << to append and pop to remove from the end.
  • Use shift, unshift to remove or add from the start.
arr.push(6)         # => [1, 2, 3, "four", 5.0, 6]
arr << 7            # => [1, 2, 3, "four", 5.0, 6, 7]
arr.pop             # => 7 (removes last element)
arr.shift           # => 1 (removes first element)
arr.unshift(0)      # => [0, 2, 3, "four", 5.0, 6]

Hashes

A hash in Ruby is a collection of key-value pairs, where keys can be symbols, strings, or other types.

h = {name: "Alice", age: 25, city: "Paris"}
puts h[:name]       # => "Alice"
puts h[:age]        # => 25
h[:country] = "France"
puts h              # => {:name=>"Alice", :age=>25, :city=>"Paris", :country=>"France"}
  • Hashes are unordered, but in Ruby 1.9+, they maintain insertion order.
  • You can use each to iterate over key-value pairs.
h.each do |key, value|
  puts "#{key}: #{value}"
end

Operations on Arrays

Ruby provides a variety of methods to manipulate arrays.

arr = [1, 2, 3, 4, 5]

# Basic operations
arr.reverse          # => [5, 4, 3, 2, 1]
arr.sort             # => [1, 2, 3, 4, 5]
arr.uniq             # => [1, 2, 3, 4, 5] (removes duplicates)
arr.include?(3)      # => true

# Array transformations
arr.map { |x| x * 2 }   # => [2, 4, 6, 8, 10]
arr.select { |x| x.even? }  # => [2, 4]
arr.reject { |x| x.even? }  # => [1, 3, 5]

Ranges

A range is a sequence of values, often used to generate numbers or work with loops.

r = 1..5         # includes 1, 2, 3, 4, 5
r = 1...5        # includes 1, 2, 3, 4 (excludes 5)

# Convert range to array
arr = (1..5).to_a    # => [1, 2, 3, 4, 5]

Ranges are useful in loops, conditionals, and array slicing.

(1..3).each { |i| puts i }    # => prints 1, 2, 3

Classes

Ruby is a pure object-oriented language, meaning every value is an object. Classes define the blueprint for objects.

class Person
  attr_accessor :name, :age   # defines getter and setter methods

  def initialize(name, age)
    @name = name              # instance variables
    @age = age
  end

  def introduce
    puts "Hi, I'm #{@name} and I'm #{@age} years old."
  end
end

# Creating an object
person = Person.new("Alice", 25)
person.introduce         # => "Hi, I'm Alice and I'm 25 years old."
  • Instance Variables (@var) are used to store object-specific data.
  • Class Variables (@@var) are shared across all objects of a class.
  • Class Methods are defined using self.method_name or def self.method_name.

Inheritance and Method Overriding

Ruby supports inheritance, where one class can inherit methods and attributes from another.

class Animal
  def speak
    puts "Generic animal sound"
  end
end

class Dog < Animal
  def speak
    puts "Woof!"
  end
end

dog = Dog.new
dog.speak           # => "Woof!"

Blocks and Yield

Blocks in Ruby are chunks of code enclosed in {} or do..end that can be passed to methods.

def my_method
  puts "Start of method"
  yield          # Executes the block passed to the method
  puts "End of method"
end

my_method { puts "Hello from the block!" }

# Output:
# Start of method
# Hello from the block!
# End of method
  • Yield is used to call the block inside a method.
  • Blocks can accept arguments.
def my_method
  yield(5)       # Passes 5 to the block
end

my_method { |num| puts num * 2 }   # => 10

Blocks can also be stored in variables as Procs or Lambdas and passed around.

my_proc = Proc.new { |x| puts x * 2 }
my_proc.call(10)    # => 20

my_lambda = ->(x) { puts x * 3 }
my_lambda.call(10)  # => 30
## Symbols
A symbol in Ruby is a lightweight, immutable identifier often used in place of strings for labels, keys, or identifiers. Symbols are denoted by a colon (`:`) followed by the name of the symbol.

```ruby
:name
:age
:city

Differences between Symbols and Strings

  • Immutable: Symbols cannot be changed once created, whereas strings are mutable.

  • Memory-efficient: Symbols are only stored once in memory, making them more efficient for repeated use.

  • Symbols are often used as keys in hashes, method names, and references to methods.

person = {name: "Alice", age: 25, city: "Paris"}
puts person[:name]    # => "Alice"

Symbols are particularly useful when the identifier doesn’t need to change or when comparisons need to be fast.

puts :name == :name    # => true

Mixins

Ruby uses mixins to allow modules to share functionality across multiple classes without inheritance. This is accomplished by including or extending Modules.

Modules

Modules are like classes but cannot be instantiated. They are used for grouping methods, constants, and other functionality that can be reused across classes.

module Walkable
  def walk
    puts "I'm walking!"
  end
end

class Person
  include Walkable   # Mixin Walkable module
end

person = Person.new
person.walk          # => "I'm walking!"

include vs extend

  • include mixes in module methods as instance methods.

  • extend mixes in module methods as class methods.

module Greetable
  def greet
    puts "Hello!"
  end
end

class Animal
  extend Greetable
end

Animal.greet          # => "Hello!" (Class method)

Exceptions

Ruby provides a robust exception-handling mechanism using begin, rescue, ensure, and raise. Exceptions allow you to manage errors in your program gracefully.

Basic Exception Handling

begin
  # Code that might raise an exception
  result = 10 / 0
rescue ZeroDivisionError
  puts "Can't divide by zero!"
ensure
  puts "This will always run"
end
  • rescue is used to capture and handle exceptions.
  • ensure runs no matter what (whether an exception occurs or not).
  • raise is used to manually throw an exception.

Raising Exceptions

def divide(a, b)
  raise ArgumentError, "Division by zero is not allowed" if b == 0
  a / b
end

begin
  divide(10, 0)
rescue ArgumentError => e
  puts e.message
end

Custom Exceptions

You can define your own exception classes by inheriting from StandardError.

class CustomError < StandardError; end

begin
  raise CustomError, "Something went wrong!"
rescue CustomError => e
  puts e.message     # => "Something went wrong!"
end

Threads

Ruby provides native support for multithreading. Threads allow you to execute code concurrently.

Creating and Running Threads

thread = Thread.new do
  puts "Thread is running"
end

thread.join   # Waits for the thread to finish
  • Thread.new creates a new thread.
  • join makes the main program wait for the thread to finish.

Passing Arguments to Threads

thread = Thread.new(10, 20) do |a, b|
  puts a + b   # => 30
end

thread.join

Thread Synchronization

Threads may access shared resources, leading to potential conflicts. Ruby provides synchronization mechanisms to avoid such issues, such as Mutex (mutual exclusion).

mutex = Mutex.new

counter = 0
threads = []

5.times do
  threads << Thread.new do
    mutex.synchronize do
      temp = counter
      sleep(0.1)
      counter = temp + 1
    end
  end
end

threads.each(&:join)
puts counter   # => 5
  • Mutex ensures that only one thread can execute a piece of code at a time, preventing race conditions.
## Snippets
This section contains useful Ruby code snippets that can be used in everyday programming.

### 1. Swap Two Variables
```ruby
a = 10
b = 20

a, b = b, a

puts a   # => 20
puts b   # => 10

2. Check If a String Contains a Substring

string = "Hello, world!"
substring = "world"

puts string.include?(substring)   # => true

3. Convert String to Symbol

str = "hello"
sym = str.to_sym

puts sym   # => :hello

4. Convert Symbol to String

sym = :ruby
str = sym.to_s

puts str   # => "ruby"

5. Flatten a Nested Array

nested_array = [1, [2, 3], [4, [5, 6]]]
flat_array = nested_array.flatten

puts flat_array   # => [1, 2, 3, 4, 5, 6]

6. Find Unique Elements in an Array

array = [1, 2, 2, 3, 3, 3]
unique_elements = array.uniq

puts unique_elements   # => [1, 2, 3]

7. Sorting an Array of Hashes by Key

people = [{name: "Alice", age: 25}, {name: "Bob", age: 20}, {name: "Charlie", age: 30}]
sorted_people = people.sort_by { |person| person[:age] }

puts sorted_people
# => [{:name=>"Bob", :age=>20}, {:name=>"Alice", :age=>25}, {:name=>"Charlie", :age=>30}]

8. Find the Largest Element in an Array

array = [10, 5, 20, 8]
largest = array.max

puts largest   # => 20

9. Iterate Over a Hash

person = {name: "Alice", age: 25, city: "Paris"}

person.each do |key, value|
  puts "#{key}: #{value}"
end
# Output:
# name: Alice
# age: 25
# city: Paris

10. Reading and Writing Files

  • Reading a File
File.open("example.txt", "r") do |file|
  puts file.read
end
  • Writing to a File
File.open("example.txt", "w") do |file|
  file.write("Hello, file!")
end

11. Get Current Date and Time

require 'date'

current_time = Time.now
puts current_time   # => Current date and time

current_date = Date.today
puts current_date   # => Current date

12. Generate a Range of Numbers

range = (1..5).to_a

puts range   # => [1, 2, 3, 4, 5]

13. Filtering an Array

array = [1, 2, 3, 4, 5]
even_numbers = array.select { |num| num.even? }

puts even_numbers   # => [2, 4]

14. String Interpolation

name = "Alice"
greeting = "Hello, #{name}!"

puts greeting   # => "Hello, Alice!"

15. Create and Use a Lambda

greet = ->(name) { puts "Hello, #{name}!" }

greet.call("Bob")   # => "Hello, Bob!"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment