Skip to main content
Caleb-Mitchell

RB100: Notes

·16 mins

INTRO #

abstraction is useful and important -one example is the interface of a phone, not important for most users to go deeper -Ruby is written in C, which translates to Assembly language, which translates to machine language, which translates to 0s and 1s. -Rubyists use Ruby to design and build higher level languages called Domain Specific Languages, or DSL’s, like Rails and Rspec.

documentation -For now, these are the three most important things to remember when reading Ruby documentation: the class or module you’re looking at, its available class methods, and its available instance methods - and how to use those methods. Knowing how to read a class’s methods will help you play around with Ruby code and develop fluency.

-instance methods can be called on any instance of the class (i.e. “world wide web”.split) -class methods are called directly from the class (i.e. String.new)

When you run a Ruby file from the command line, the code gets executed by what’s called an interpreter.

RubyGems/gems

  1. a collection of Ruby files, or Ruby library, that performs a certain task
  2. the publishing system behind organizing, listing, and publishing those libraries/gems -A gem is said to have been “cut” when a new version becomes available.

THE BASICS #

literals -a literal is any notation that lets you represent a fixed value in source code -i.e. strings, integers, floats

strings -a list of characters in a specific sequence -double quotes allow for string interpolation, single quotes do not

symbols -created by placing a colon before a word -used when you want to reference something like a string, but don’t ever intend to print it to the screen or use it -often referred to as an immutable string

nil -nothing! -you can use the nil literal to refer to nil, x = nil -you can check if something is a nil type using .nil?, “Hello”.nil? returns false

numbers -integers and floats

operations -division (/) only returns an integer

modulo vs remainder -Modulo operations (%) return a positive integer when the second operand is positive, and a negative integer when the second operand is negative. -Remainder operations (.remainder method, i.e. 16.remainder(5) returns 1) return a positive integer when the first operand is positive, and a negative integer when the first operand is negative. -this is confusing, in general, try to work with positive integers exclusively

multiplying and dividing floats -whenever you use a float in an operation, Ruby always returns a float

equality comparison -uses the == operator

type conversion -can convert a string to an integer, using .to_i -also .to_s, .to_f

basic data structures -arrays and hashes (dictionaries)

-arrays can contain any Ruby objects, seperated by ,’s -hashes contain key-value pairs

expressions and return -**Ruby expressions always return a value, even if that value is nil, or an error

puts vs return -puts prints to the screen, returns nil


VARIABLES #

Variables are used to store information to be referenced and manipulated in a computer program. -have descriptive names -think of them as containers that hold information, they label and store data in memory

*Think hard about variable names -accurately descriptive, understandable to another reader

A variable’s scope determines where in a program a variable is available for use. -this scope is defined by *where the variable is initialized or created. -in Ruby, variable scope is defined by a block!

Inner scope can access variables initialized in an outer scope, but not vice versa

  • Note: the key distinguishing factor for deciding whether code delimited by {} or do/end is considered a block (and thereby creates a new scope for variables), is seeing if the {} or do/end immediately follows a method invocation. (for loops are not a method invocation!)

5 types of variables:

  1. constants
  2. global variables
  3. class variables
  4. instance variables
  5. local variables

Constants are declared by capitalizing every letter in the variable’s name, per Ruby convention. -they store data that never needs to change, although Ruby does allow you to change it unlike most programming languages -MY_CONSTANT = ‘I am available throughout your app.’

Global variables are declared by starting the variable name with the dollar sign ($). -available through entire app, no scope boundaries -Rubyists tend to avoid these, as there can be unexpected complications -$var = ‘I am also available throughout your app.’

Class variables are declared by starting the variable name with two @ signs. -accesible by instances of the class, as well as the class itself -you use these when you need to declare a variable that is related to a class, but each instance of that class does not need its own value for this variable -they must be initialized at the class level, but they can be altered using class or instance method definitions -@@instances = 0

Instance variables are declared by starting the variable name with one @ sign. -available throughout the current instance of the parent class -they can cross some scope boundaries, but not all of them -don’t use these until i know more about them -@var = ‘I am available throughout the current instance of this class.’

Local variables are the most common variables you will come across and obey all scope boundaries. -declared by starting the variable name with neither $ nor @, and all lowercase -var = ‘I must be passed around to cross scope boundaries.’


METHODS #

There is a feature in most programming languages called a procedure, allowing you to extract common code to one place. -In Ruby this is called a method

begins with def keyword, then body, then end keyword

parameters are used when you have data outside of a method definition’s scope, but need access to it within the method definition

calling a method is also sometimes called “method invocation”

give parameters good names just like variables

methods allow us to make changes in one place that affect many places in our program

when defining methods, always make sure that a method works, whether given parameters or not -can provide a default parameter to avoid this -i.e. def say(words=‘hello’), makes this default value

*parentheses are optional when calling methods as a style choice -instead of say(“hi”), it could just be writted say “hi”

variables created within a method can only be accessed within the method -local variables within a method definition cannot access data outside of the method definition (unless the data is passed as an argument)

2 ways to call methods! -obj.method -and- method(obj) -easiest to think of the former as the method modiying the ‘explicit caller’

sometimes calling a method can alter the argument permanently -this is called ‘mutating the caller’ -this would be the only way to alter variables outside a method definition’s scope -for example, the pop method mutates a calling array

in a way, ruby is both a “pass-by-value” and a “pass-by-reference” language

**Ruby methods ALWAYS return the evaluated result of the last line of the epression unless an explicit return comes before it -using the return keyword will *immediately return whatever follows

very important in regards to chaining methods together: **if anywhere along the chain, something returns nil or an exception is thrown, the entire chained call will break down

you can actually pass method calls as arguments to other methods -nested method calls! (definitely use parentheses)

the call stack, casually called the stack -like a stack of books, can put the new book on top or remove the topmost book (called frames in call stack) -call stacks initially have one item, the stack frame (main method) -every time the stack is invoked the location in the stack is saved, and items are either *pushed or *popped

methods, blocks, procs, and lambdas also use the call stack

Ruby has enough size in call stack for more than 10,000 stack entries -if you run out you see a SystemStackError exception


FLOW CONTROL #

Wanting your data to do the right thing when it’s supposed to, is referred to as “conditional flow”, using “conditionals” -a conditional is a fork, or many forks, in the road

(<, >, <=, >=, ==, !=, &&, ||)

A boolean value is either true or false, nothing else

The expressions or values that an operator uses are its operands. In comparisons, the expressions to the left and right of the operator are the operands.

When comparing strings, the comparison is character-by-character. Ruby moves from left-to-right in the strings looking for the first character that is different from its counterpart in the other string. -then compares that one -like alphabetizing numbers

! - the “not” operator. When you add this in front of a boolean expression it will change that boolean value to its opposite. -You can think of !true as saying “not true”.

***Ruby ‘order of precedence’ for operators, highest order of precendence to lowest

  1. <=, <, >, >= - Comparison
  2. ==, != - Equality
  3. && - Logical AND
  4. || - Logical OR

The ternary operator uses a combination of the ? and : irb :001 > true ? “this is true” : “this is not true” => “this is true”

irb :001 > false ? “this is true” : “this is not true” => “this is not true”


LOOPS & ITERATORS #

*The simplest loop in Ruby is the ‘loop method’ -{ … } or do … end -will loop until break statement or ctrl + c -break will exit a loop, not the entire program -next keyword will skip the rest of the current iteration of a loop, and start executing the next iteration - next if conditional

*A while loop is given a parameter that evaluates to a boolean, continues while the boolean is true -the loop must modify the variable or you’ll have an infinite loop

*The until loop is the opposite of the while loop -expressive feature of ruby

*do/while loop is like a while loop (you don’t use while though, it’s just a plain loop method containing a break if case) -but, the code gets executed once *before checking the conditional. the conditional is placed at the *end instead of the beginning -example in Ruby

perform_again.rb #

loop do puts “Do you want to do that again?” answer = gets.chomp if answer != ‘Y’ break end end

*for loops are used to loop over a colletion of elements -they have a definite end -*for i *in range do -> end -for loops return the collection of elements after it executes, while loops return nil -could also loop through an array with for loop

*conditionals within loops -can be useful to use if, next, break to control flow within loops -most Rubyists prefer iterators over loops

*iterators are methods that naturally loops over a given set of data and allow you to operate on each element in the collection -use the .each method for arrays -each time you iterate over an array, you assign the value of each element to a variable to use it -a block is just some lines of code ready to be executed -{} when everything can be contained on one line, do/end for multi line operations

i.e. names.each do |variable| body end

or

names.each { |variable| body }

**recursion is another way to create a loop in ruby, it is the act of calling a method from within itself -example: doubling a number until the pre-doubled number is 10 or greater

def doubler(start) puts start if start < 10 doubler(start * 2) end end

The key concept with recursion is that there is some baseline condition that returns a value, which then “unwinds” the recursive calls. You can think of the successive recursive calls building up, until some value is returned, and only then can the recursive calls be evaluated.


ARRAYS #

array is an ordered list of elements that can be of any type

.first and .last methods can find first and last elements of an array -can also index with brackets(zero indexed)

pop method -mutates the caller -‘pops’ off last value of array permanently, and returns it

push method -adds an item to array permanently - array.push(the pushed object) -can also do this with shovel operator « -mutates the caller! -unshift method, like push, but adds value to *beginning of array/list

map/collect methods -iterates over an array applying a block to each element of the array, returning a new array with those results, do not mutate the caller

have to memorize which methods mutate the caller and which don’t

delete_at method eliminates the value at a certain index from an array -mutates the caller, is permanent -a.delete_at(1) delete method deletes *all instances of the provided value from the array -a.delete(“cat”)

uniq method iterates through an array, deletes any duplicate values that exist, returns the resulting array -a.uniq – does not mutate the caller -if you do .uniq! it *will mutate the caller

select method, iterates over an array, returns a new array that includes any items that return true to the expression provided -numbers.select { |number| number > 4 } -does not mutate the caller

! (bang suffix) indicates that the method will change/mutate the caller permamently -check the documentation to see if the method will behave destructively(mutates the caller)

you can compare arrays for equality using the == operator

Ruby does the to_s method automatically behind the scenes if we use string interpolation to print an array to the screen: irb :001 > a = [1, 2, 3] => [1, 2, 3] irb :002 > “It’s as easy as #{a}” => “It’s as easy as [1, 2, 3]”

common array methods -include? - checks to see if the argument given is included in the array, question mark at end of method means it is called a predicate -flatten - take an array that contains nested arrays and create a one-dimensional array. -each_index - iterates through like each, but the variables represents each index number instead of each value -each_with_index - gives us the ability to manipulate both the value and the index by passing in two parameters to the block of code. (like using each in a hash) -sort - returns a sorted array -product - returns an array that is a combination of all elements from all arrays.

each vs map -each is preferred over a for loop -if given a block, each returns the collection it was invoked on, if no block was given it returns an Enumerator -each returns the original collection of values, map/collect creates and returns a new array!

each is for iteration, map is for transformation

when you reference an index of a string that is beyond the length of the string, Ruby returns nil and doesn’t throw an error.


HASHES #

A hash is a data structure that stores items by associated keys. This is contrasted against arrays, which store items by an ordered index. Entries in a hash are often referred to as key-value pairs. This creates an associative representation of data.

merge method will combine two hashes

each method with hashes, use two variables!

person.each do |key, value| puts “Bob’s #{key} is #{value}” end

can pass a hash as an argument to a method -greeting(“Bob”, age: 62, city: “New York City”) -Notice the curly braces, { }, are not required when a hash is the last argument, and the effect is identical to the previous example. This convention is commonly used by Rails developers. Understanding this concept alone should help you decipher some previously cryptic Rails code!

When deciding whether to use a hash or an array, ask yourself a few questions: -Does this data need to be associated with a specific label? If yes, use a hash. If the data doesn’t have a natural label, then typically an array will work fine. -Does order matter? If yes, then use an array. As of Ruby 1.9, hashes also maintain order, but usually ordered items are stored in an array. -Do I need a “stack” or a “queue” structure? Arrays are good at mimicking simple “first-in-first-out” queues, or “last-in-first-out” stacks. —–hash vs array?? - label?/order?/structure? —

can use any other object, even arrays, as a key in hashes -forced to use old “hash rocket” style if not using symbols

common hash methods -has_key? - allows you to check if a hash contains a specific key. It returns a boolean value. -select - allows you to pass a black and will return any key-value pairs that evaluate to true when ran through the block -fetch - allows you to pass a given key and it will reutrn the value for that key if it exists, can also specify an option for return if key is not present(should probably be used so that error is not thrown searching by bracket notation with nothing found) -to_a - returns an array version of hash called upon, is not destructive -.keys and .values - returns the keys or values respectively

any version of Ruby since 1.9 maintains the in order of values in a hash, but not older versions


MORE STUFF #

Regex stands for regular expression -A regular expression is a sequence of characters that form pattern matching rules, and is then applied to a string to look for matches. -Creating regular expressions starts with the forward slash character (/). Inside two forward slashes you can place any characters you would like to match with the string. -We can use the =~ operator to see if we have a match

irb :001 > “powerball” =~ /b/ => 5

-On top of the =~ operator, we can use the match method to perform regex comparisons as well. This method returns a MatchData object that describes the match or nil if there is no match. -can use a MatchData object to act as a boolean value

Ruby Standard Classes -depending on the complexity of a specific operation, look first in Ruby’s standard classes

Variables as Pointers -variables are pointers to physical space in memory -or, variables are labels

Blocks and Procs -The block must always be the last parameter in the method definition. -Procs are blocks that are wrapped in a proc object, and stored in a variable to be passed around.

-Procs can also take arguments if specified.

Exception Handling -Exception handling is a specific process that deals with errors in a manageable and predictable way. -The reserved word rescue will show up a lot in your Ruby career so it’s better to know what it is sooner than later. -Ruby has an Exception class that makes handling these errors much easier. It also has a syntactic structure using the reserved words begin, rescue, and end to signify exception handling.

-We are effectively rescuing our program from coming to a grinding halt.

-We can also rescue pre-existing errors when we are writing our code.

Exceptions and Stack Traces -For the purposes of this section an exception can be viewed as synonymous with an error. -when something does go wrong, usually we say “an exception is raised”.

-Part of this involves understanding how execution works within Ruby, involving the ‘stack’. -Now we can make a little more sense of the output from the error, as it provides a detailed trace (known as a stack trace) that shows the flow of execution and where the error occurred.


DPP interview notes #

**make sure i understand string mutability foo = ‘hello’ bar = foo

foo += ‘, world’ p bar # ‘hello’

vs.

foo « ‘, world’ p bar # ‘hello, world’

– variables are pointers to addresses in memory!!

**you don’t need string interpolation if defining a method to puts a variable that is storing a string, just puts variable

**if i need to make a change in code, THINK, before i start deleting or making changes

**values are said to be ‘truthy’, not ‘true’, unless it is literally the value ‘true’ foo = 8 if 7 puts foo else puts bar

8 (because 7 is truthy) #

** if/else statements are NOT blocks, lol -a block is a do..end/curly braces paired with a method call

**write a function, that accepts two integers as arguments, which returns the sum of all numbers inclusive of the range of those two numbers

def add_range(x, y) result = 0 x.upto(y) do |i| result += i end return result end

puts add_range(1, 5)