A Cheat Sheet for Ruby
Tags: ruby, beginners, programming
Published: 2022-08-23 01:33:05

A lot of this can be cut out by Active Record and/or Rails but it's always good to know the bare bones. 

Below are brief references and explanations to some basic parts of Ruby code. I recommend copying this and pasting it into a code editor so it becomes color coded (and easier to read).

---

## VARIABLE DECLARATIONS

```
attr_reader :age
# makes "age" something you can only display, not edit (getter method)

attr_writer :name
# makes "name" something you can change, not display (setter method)

attr_accessor :owner
# makes "owner" able to display & edit (getter & setter)
```

## METHODS

```
#                               v default value
def greet_with_default (name="programmer")
    puts "Hello, #{name}!"
end

# def -> identifies it as a method
    # parentheses are optional if not passing data
    # last line of a method is the return value unless you put return
# end -> end of method (always needed)

```

---

```
# using keyword arguments make it less likely to break (____:)

def happy_birthday(person:, current_age:)
  puts "Happy Birthday, #{person}"
  current_age += 1
  puts "You are now #{current_age} years old"
end

# call the method with the keywords and values
happy_birthday(current_age: 31, person: "Carmelo Anthony")
```

---

```
def self.method 
    self.order
end
# ^self refers to class in both because it's in method name

def method
    self
end
# ^self refers to an instance because it's not in method name
```

---

```
# initialize without knowing what arguments you have
def initialize (args = nil)
    # upon initialization (start) accept (hash), default = nil

    if args
    #  ^ if there is a hash do stuff

            # v go through each key in hash
        args.each_key do |key, value|
                         # ^look at key & value
 
            self.class.attr_accessor(key)
            # ^ dynamically set methods automatically for all keys
        
            self.send("#{key}=", args[key])
            # ^send attribute to the self's class
        end
    end
end

```

---

```
private
# any methods under "private" cannot be called by explicit receiver (Dog.privatemethod)
# can be called by other methods
```

## CLASSES

```
class Dog < Pet
# Dog is inheriting all the stuff from Pet class (separate file)

    extend FancyDance::ClassMethods
    # get module class methods

    include FancyDance::InstanceMethods
    # get module instance methods

    @@dog_count = 0
    # class variable

    def initialize
        # upon initialization
        super
        # do *initialize* from inherited file (Pet) first
        # can take an argument EX: super(name)

        @@dog_count += 1
        # add 1 to class variable
    end

    def get_adopted(owner_name)
        self.owner = owner_name
        # self refers to the instance of Dog that is being called
    end
end

# objects in Dog are accessed by dot notation
fido = Dog.new("Fido")
# fido = new instance of Dog, passing in "Fido" as name

fido.get_adopted("Sophie")
# sets "Sophie" as owner
```

## MODULES

```
module FancyDance
    # can nest modules
    module InstanceMethods
        def twirl
            "I'm twirling!"
        end

        def initialize
            self.class.all << self
            # put current instance in matching class array
            # EX: @@dog_list << self
        end
    end

    module ClassMethods
        def metadata
            "Dogs love to dance."
        end
    end
end

fido.twirl
# instance output "I'm twirling!"

Dog.metadata
# class output "Dogs love to dance."
```

## HASHES

```
# only use bracket notation
my_hash = { key1: "value1", key2: "value2" }
my_hash[:key2]
# => "value2"

# Equivalent to:
{ :key1 => "value1", :key2 => "value2" }

my_hash.keys
# returns the keys in my_hash

my_hash.values
# returns the values in my_hash

my_hash.empty?
# eval if hash is empty (true/false value)

my_hash.delete(:key1)
# deletes (key1), returns edited hash

my_hash.merge(other_hash)
# returns edited my_hash with other_hash appended
```

## ARRAYS

```
list.detect{|a| a.name == name}
# returns the first element that matches (array only)
# If no block, then it returns enumerator (name).

list.include? "blah"
# does list include "blah"? true/false value

[1, 2, 3].sum
# => 6 (adds values together)

[1, 1, 2, 3, 3, 5, 5].uniq
# => [1, 2, 3, 5] (returns only unique values)

[1, 3, 400, 7].length
# => 4 (returns number of items in array)

[5, 100, 234, 7, 2].sort
# => [2, 5, 7, 100, 234] (sorts smallest to largest)

[1, 2, 3].reverse
# => [3, 2, 1] (put in reverse order)

list.count 
# counts amount of items in list

list.first
# returns first thing in array

list.last
# returns last thing in array

list.push("M&Ms")
list << "M&Ms"
# Both put M&Ms at end of array, returns edited array

list.unshift("Cake")
# puts Cake at beginning of array, returns edited array

list.pop
# removes last item, returns removed item

list.shift
# removes first item, returns removed item

list1.concat(list2)
# combine arrays into original array (list1), returns edited array

```

## STRINGS

```
var.gsub(' ', '-')
# substitute space for dash (string only)

first_name, last_name = full_name.split
# default of split is by space (string only)
```

## MAP / FILTER / FIND / SORT

```
def spicy_foods 
  [
    { name: 'Green Curry', cuisine: 'Thai', heat_level: 9 },
    { name: 'Buffalo Wings', cuisine: 'American', heat_level: 3 },
    { name: 'Mapo Tofu', cuisine: 'Sichuan', heat_level: 6 }
  ]
end
```

---

```
#MAP the foods in the list by name, returns array of names
spicy_foods.map{ |food| food[:name] }

# Equivalent to:
spicy_foods.map do |food|
    food[:name]
end
```

---

```
#FILTER foods by heat level > 5, returns array of objects
spicy_foods.filter{ |food| food[:heat_level] > 5 }

# Equivalent to:
spicy_foods.filter do |food|
    food[:heat_level] > 5 
end
```

---

```
#FIND food that = what you are looking for, returns 1 object
spicy_foods.find{ |food| food[:cuisine] == cuisine }

# Equivalent to:
spicy_foods.find do |food|
    food[:cuisine] == cuisine
end
```

---

```
#SORT by given key (ASCII value), returns array of objects (no change array)

# (<=>) combined comparison operator, returns:
    # 0 if the first operand equals the second,
    # -1 if the first operand is less than the second, and
    # 1 if the first operand is greater than the second.

# sort method, need 2 objects passed to it
spicy_foods.sort do |food1, food2|
  food1[:name] <=> food2[:name]
end

# sort_by only needs 1 element passed to it
spicy_foods.sort_by {|food| food[:heat_level]}

# Equivalent to:
spicy_foods.sort_by do |food|
    food[:heat_level]
end
```

## LOOPS

```
num = 10
until num == 0
    puts "#{num}"
    num -= 1
end
#until the num = 0, count down
```

---

```
num = 0
while num <= 100
    puts "#{num}"
    num += 1
end
#while num is <= 100, count up
```

---

```
10.times do |i|
  puts "i is: #{i}"
end
# Equivalent to:
10.times { |i| puts "i is: #{i}" }
```

---

```
# v range
(1..20).each do |b|
  puts "#{b}"
end
# ^ puts value of b while iterating through range of 1-20
```

## PRINT TO CONSOLE

```
puts "Hello World!"
# puts -> console.log() with line break @ end
    # makes the data into a string

print "Hello"
# print -> console.log() no line breaks


p [1, 2, 3]
# p -> output data in nicer format by calling .inspect
# equivalent to calling v
    # puts [1, 2, 3].inspect


pp [{ id: 1, hello: "World" }, { id: 2, hello: "Ruby" }, { id: 3, hello: "Moon" }, { id: 4, hello: "Learner" }]
# pp -> pretty printing for complex data (nested arrays/hashes)
```

---

Hope this was a good reference!

Please let me know if you think I'm missing anything significant in the comments down below.