## Week 2
# Get the Ruby Then Ride the Rails
---
# Quick Logistics
- Office Hours
- Sign up 2 hours before
- Homework 2
- Due next Wed (10/2) before class
---
# Agenda
- In-depth Ruby syntax
- Object types
- Looping
- String and arrays
- Object-oriented programming
- Modules
- Intro to Rails
---
# Recap
----
# Everything Is An Object
```ruby=
{
1 => Integer,
‘String’ => String,
:symbol => Symbol,
[] => Array,
{} => Hash,
nil => NilClass
}
```
---
# Variables
----
# No Typedef
* Similar to Python
* Can be any lowercase word with _
* `hello = 3`
* `decal = 'decal'`
* More types of variables explained later...
----
# putting vs printing
- `put`
- adds a new line after executing
- `print`
- no new line after executing
---
# Numbers
----
# Numbers
- Integers
- 123, -99
- Floats
- 23.5
----
# Number Demo
```bash
$ irb
> 1 + 2
> 1.0 + 2
> 1 + 2.0
> 3 / 2
> 3.0 / 2
> 3 / 2.0
> -99.abs
```
----
# Number Demo
```bash
$ irb
> 1 + 2 #=> 3
> 1.0 + 2 #=> 3.0
> 1 + 2.0 #=> 3.0
> 3 / 2 #=> 1
> 3.0 / 2 #=> 1.5
> 3 / 2.0 #=> 1.5
> -99.abs #=> 99
```
---
# Strings
----
# Strings
- Representation of text
- Quite important for Web!
- (everything is text)
----
# Strings
Similarly to Python, you can use double and single quotes
```ruby=
"This is one String!"
'And this is another one.'
```
* Basically the same with slight difference. More in the demo.
----
# String Demo
Discuss with your neighbor your findings.
Try the following in irb:
```bash
$ irb
> "snow" + "ball"
> "hi" + "hi" + "hi"
> "hi" * 3
> "school" << "yard"
> "hello".upcase
> "hello".capitalize
> "hello".length
> "hello".reverse
> puts "one\ntwo\nthree"
```
----
# String Interpolation
- `name = "Ada"`
- `puts "Hello, " + name + "!"`
- `puts "Hello, #{name}!"`
- `puts 'Hello, #{name}!'`
---
# True, False, nil
- `true` and `false` are boolean objects
- `nil` represents "nothing"
- Methods always return exactly one thing (i.e. one object)
- Therefore, `nil` is to return nothing
- Falsey values
- `nil`
- `false`
- Everything else truthy
---
# Symbols
* Symbols are like strings, except they are code.
* Symbols are a rather strange concept to be honest, and we only introduce them because symbols are used so often and widely that you’ll very likely find them used in code elsewhere.
A symbol is written like this: `:something`
----
# More symbols
* One rule of thumb is that if the text at hand is “data”, then use a string. If it’s code, then use a symbol, especially when used as keys in hashes.
* Another way of looking at symbols is that they aren’t really text, even though they read well. Instead they are unique identifiers.
----
# Technical Difference
Try this in your terminal.
```bash
$ irb
> "a string".object_id
=> 70358630335100
> "a string".object_id
=> 70358640625960
> "a string".object_id
=> 70358644379620
```
----
With Symbols however:
```bash
> :a_symbol.object_id
=> 1086748
> :a_symbol.object_id
=> 1086748
> :a_symbol.object_id
=> 1086748
```
---
# Arrays
----
# Arrays
- An Array is created by separating values by commas, and enclosing this list with square brackets, like so:
- `[1, 2, 3]`
- We can store any combination of objects inside as such:
- `["A string", 1, true, :symbol, 2]`
----
# Retrieving From Arrays
* To retrieve a certain element by the way of referring to its position: Please get me the element at position 1!
In Ruby, you can do this with square brackets like so:
```ruby=
words = ["one", "two", "three"]
puts words[1]
```
----
# Adding To Arrays
In order to add an element to the end of an existing Array you can use the operator <<, called “shovel operator”, push, and or unshift, like so:
```ruby=
words = ["one", "two", "three"]
words << "four" # add to the end
words.push("five") # add to the end
words[5] = "six" # add to the end
words.unshift("zero") # add to the front
```
----
```ruby=
puts words
#=> ["zero", "one", "two", "three", "four", "five"]
```
----
# Updating Arrays
* You could also overwrite existing elements the same way.
```
words = ["one", "two", "three"]
words[0] = "uno"
puts words[0]
```
* So, this would now output uno.
----
# Discussion
What happens if you try to access an index outside of bounds?
----
# Array Demo
Create an array with three objects inside of it. Then try to access the fourth object. What do you see?
```bash
> words = ["one", "two", "three"]
> words[3]
```
----
As mentioned before all ruby methods must return an object, when there is nothing to return a method will return nil, meaning nothing.
---
# Hashes
----
# Hashes
* Similar to Python dictionaries
* key/value pairs
* Look up values using keys
* Can have as many key/value pairs as you like
----
# Creating a Hash
* In Ruby you can create a Hash by assigning a key to a value with =>, separate these key/value pairs with commas, and enclose the whole thing with curly braces.
This is how it looks:
```ruby=
{ "one" => "eins", "two" => "zwei", "three" => "drei" }
```
or
```ruby=
{ "one" => "eins", "two" => "zwei", "three" => "drei" }
```
* This defines a Hash that contains 3 key/value pairs.
----
# An alternative
A new way of creating hashes with symbols. Looks a lot like JSON.
```ruby=
{ one: "eins", two: "zwei", three: "drei" }
```
----
# Looking up a value
* Now, how do you actually look up the value that is associated with the key "one"? We accomplish this like so:
```ruby=
dictionary = { "one" => "eins", "two" => "zwei", "three" => "drei" }
puts dictionary["one"]
```
----
# Setting a key to a value
Just like with Arrays, there’s a way to add key/value pairs on an existing Hash:
```ruby=
dictionary = { "one" => "eins",
"two" => "zwei", "three" => "drei" }
dictionary["zero"] = "ichi"
puts dictionary["zero"]
```
This prints out `"ichi"`
----
You can also overwrite existing key/values the same way.
```ruby=
dictionary = { "one" => "eins", "two" => "zwei", "three" => "drei" }
dictionary["one"] = "uno"
puts dictionary["one"]
```
So, this would now output uno.
You can even try to access something that is not there.
----
# Hash Demo
Discuss with your neighbor what you see outputed when you run the following commands:
```bash
> dictionary = { "one" => "eins" }
> dictionary.fetch("one")
> dictionary.fetch("two")
> dictionary = { "one" => "eins", "two" => "zwei" }
> dictionary.keys
> dictionary.length
> dictionary.size
```
---
# Blocks & Loops
----
# Some examples
```ruby=
5.times do
puts "Oh, hello!"
end
5.times { puts "hello!" }
[1, 2, 3, 4, 5].each do |number|
puts "#{number} was passed to the block"
end
[1, 2, 3, 4, 5].each { |number| puts "#{number} was passed to the block" }
```
----
# While
```ruby=
while x >= 0
puts x
x = x - 1
end
```
----
# Until
```ruby=
until x < 0
puts x
x -= 1
end
```
----
# do/while loop
```ruby=
loop do
puts "Do you want to do that again?"
answer = gets.chomp
if answer != 'Y'
break
end
end
```
----
# For loop
Loops from 1 to x.
```ruby=
for i in 1..x do
puts i
end
```
----
# Blocks with return values
```ruby=
p [1, 2, 3, 4, 5].collect
{ |number| number + 1 }
```
This will take the array of numbers, and transform it into another array. Basically map in Ruby.
```ruby=
p [1, 2, 3, 4, 5].select
{ |number| number.odd? }
```
This is filter in Ruby.
---
# Conditionals
----
# Some Examples
```ruby=
number = 5
if number.between?(1, 10)
puts "The number is between 1 and 10"
elsif number.between?(11, 20)
puts "The number is between 11 and 20"
else
puts "The number is bigger than 20"
end
```
----
# Unless
```ruby=
unless number.even?
# runs if `number` is NOT even
else
# runs if `number` is even
end
```
----
# One line if
if then short hand:
```ruby=
puts "Santa's On His Way!" if today == ChristmasEve
```
if else shorthand:
```ruby=
today == ChristmasEve ? (puts "Santa's On His Way!") : (puts "Snow")
```
----
# Fancy things
```ruby=
dictionary = { :one => "eins",
:two => "zwei", :three => "drei" }
key = :four
if dictionary[key]
puts "The dictionary defines a
value for the key #{key}."
else
puts "The dictionary does not
define a value for the key #{key}."
end
```
---
# Operators
----
# Logic Operators
* `and` and `&&`
* `or` and `||`
* `not` and `!`
*Note: symbol operation takes precendence over words*
----
# Arithmetic Operators
Arithmentic Operators
* `+` addition
* `-` subtraction
* `*` multiplication
* `/` division
* `**` exponent
* `%` modulus
----
# Comparison Operators
* `<` or `<=`
* `>` or `>=`
* `<=>`
* `'A'.equals('A')`
----
# Operator Demo
Try the following in irb:
`> 1 == 1.0`
`> 1.equals(1.0)`
`> 1 <=> 3`
Also play around with the other operators.
---
# Methods
----
# Writing Methods
Suppose we need to define a simple method that takes a number, adds the number 2 to it, and returns the result. Here’s how we can do that:
```
def add_two(number)
number + 2
end
puts add_two(3)
```
*Note: return is optional in Ruby. By default Ruby returns the last object it encounters.
----
# Method Demo
Create a method that takes in an integer as an argument and returns the integer squared.
---
# Objects
Everything in Ruby is an object. Run the following in irb:
```
> "this is a string".class
> "this is a string".is_a?(String)
```
* In ruby Classes create objects. Objects are instances of classes.
----
# What does that mean?
* Classes have a bunch of characteristics, but most importantly, every class defines a number of methods.
* Every time a new object is created (“instantiated”) from this class this new object get (“inherits”) all of these methods. Objects inherit methods from their classes.
----
# Passing Arguments
You can pass arguments into the object methods.
```bash
> name = "Ruby Monstas"
> name.delete("by Mo")
```
# Here are more examples:
----
```bash
> 5.odd?
=> true
> 5.even?
=> false
> 5.between?(1, 10)
=> true
> name = "Ruby Monstas"
> name.start_with?("R")
=> true
> 1.methods.sort
=> [:*, :+, :-, :/, :between?, :even?, :odd?, :zero?]
```
---
# Classes
----
# Class Examples
Since we have now looked at some of the basic building blocks lets disect an already created class.
```ruby=
class Calculator
def plus(number, other)
number + other
end
def minus(number, other)
number - other
end
def multiply(number, other)
number * other
end
end
calculator = Calculator.new
puts calculator.plus(2, 3)
puts calculator.minus(2, 3)
puts calculator.multiply(2, 3)
```
----
# Initialization
```ruby=
class Person
@@eyes = 2
def initialize(name)
@name = name
end
end
person = Person.new("Ada")
p person
```
What happens when we run the following?
```ruby=
p person.name
```
----
----
# Attribute Getters
```ruby=
class Person
def initialize(name)
@name = name
end
def name
@name
end
end
```
What if we wanted to change our name? Can we do this the way the code is currently written.
----
# Attribute Writers
To change to the name we would need to add the following method.
```ruby=
def name=(newName)
@name = newName
end
```
----
# Dont want to write a lot
Use the shorthand getter and writer
```ruby=
class Person
attr_accessor :name
def initialize(name)
@name = name
end
ar
end
```
Alternatively
* `attr_writer` creates the writer
* `attr_reader` creates only the reader
----
# Class Demo (challenging)
Suppose we are given the following class.
```ruby=
class Person
def initialize(name)
@name = name
end
def name
@name
end
end
```
We create two people.
```ruby=
person = Person.new("Anja")
friend = Person.new("Carla")
```
write a method that create the following behavior.
```ruby=
person.greet(friend)
=> Hi Carla!
```
----
# Solution
```ruby=
class Person
# methods from above ...
def greet(other)
puts "Hi " + other.name + "!"
end
end
```
---
# Modules
----
# About Modules
- Similar to classes
- Storage for methods
- Not instantiated
- i.e. not possible to create objects from module
- no method `new`
- Include in class and able to use its methods
----
# Module Example
```ruby=
module Cream
def cream?
true
end
end
class Cookie
include Cream
end
cookie = Cookie.new
p cookie.cream?
```
What will this print?
---
# What is Rails?
(baby don't hurt me)
----
# Requests in Review
- Last week we were talking about "client-side" web
- Sending Requests to Websites to ask for or send info
- The "job" of a website, is to receive and respond to these requests
----
# Ruby on Rails!
- Ruby on Rails is a 'framework' that helps us respond to requests, with nice solutions for **modeling** and **templating**.
- What's a framework?
- Why Ruby on Rails?
- `rails new`
- *a whole new world plays in the background*
----
# The Router + Controller Relationship
- Router receives requests and sends it to the relevant controller
- Controller executes a function and returns text!
----
<div style="display: flex; justify-content: center;">
<img src="https://i.imgur.com/ya5wXmM.png"></img>
</div>
---
# Rails Demo
----
# Outline
- Run `rails new`
- What happens?
- Create a controller, add two basic action
- Create a route to map to those actions
---
# Things We Learned
- Relationship between Routers, Controllers, and Views
- How to create a route and map it to an action
---
# Homework 2 & Attendance
<img src="https://media1.tenor.com/images/23189d456e0608040773536982af3b9b/tenor.gif"></img>
- Ruby is super slick
- Use your resources!
- OH and Piazza