## 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