Identify fundamentals and concepts of the Ruby langauge
Utilize different primitive types, control structures, and methods in Ruby
Humble Origins
Ruby is an object-oriented language suitable for writing day to day scripts as well as full-scale applications. Yukihiro Matsumoto, or "Matz", began work on Ruby back in 1993, because he wanted a language that made him productive while being fun to use. Initially popular in Japan, Ruby has been finding its way into the hearts of programmers all over the world.
Ruby stylistically conforms to the snake_case convention
While Ruby is a general purpose language that can be used for many purposes, we'll be applying it to a web development framework called Rails. We learned JavaScript first because it's the only language that runs natively in browsers, and we'll be utilizing some JavaScript for our front-end code, while utilizing Ruby for our back-end code.
You'll also find that while Ruby is a functional language, functions cannot be passed into other functions (functions are not first-class citizens). However, its object-oriented capabilities and clean syntax provide different strengths as a language. The widely used Rails framework also provides an opinionated development workflow, which can lead to faster development.
Comments
In JS, we use line and multiline comments.
// here's a line comment/* And a multiline comment*/
In Ruby, multiline comments exist, but we generally use line comments with hashtags, for readability.
# here is a line comment# here is a block# of comments# for you to read
Variables
Local variables start with a lowercase letter. No var necessary.
my_variable = 5puts my_variable#=> 5
Constants
Mostly, we're able to change what a variable's holding if we so choose – constants are designed for the opposite. Constants are meant to be placeholders that never change.
Note that if we try to reassign a constant, the reassignment still succeeds! All the constant syntax does is throw an error on reassignment.
Data Types
Nothingness
Just as Javascript uses undefined or null, ruby uses nil
my_bank_account = nil
Booleans
A binary representation: either true or false
is_operating = trueis_broken = false
Numbers
Datatypes used to represent a number
Fixnum: 23
Bignum: 23238923859348534535
Float: 23.23
Strings
A primative datatype used to represent a string of characters
Methods
.split.index.upcase.downcase.sub.gsub.capitalize
Examples
person = 'instructor'person.split('')#=> ["i", "n", "s", "t", "r", "u", "c", "t", "o", "r"]person.index('tr')#=> 3person.upcase#=> "INSTRUCTOR"person.downcase#=> "instructor"person.sub('r','a')#=> "instauctor"# note that only the first character is replacedperson.gsub('r','a')#=> "instauctoa"# note that all character instances are replacedperson.capitalize#=> "Instructor"person.reverse#=> "rotcurtsni"person.length#=> 10
Operators
+-/*** #exponent% #modulo+=-=*=/=**===!=!||&&
Note that Ruby has a === operator, but no !== operator. In fact, the operator means something different in Ruby. We'll touch on this when we get to ranges. You can use the .equal? function as an identity operator.
.sort.reverse.concat.length.push # (<<).shuffle.shift.unshift.slice # (negative indicies or ranges, use ! to "splice").first.last.delete.delete_at.inspect
a_range = (1..10) # includes 10another_range = (1...10) # not including 10letters_range = ('a'..'z')
typecasting in action
another_range.to_a=> [1,2,3,4,5,6,7,8,9]
Using === to determine if an element is within a range or set
another_range ===3#=> true
Symbols
An immutable sequence of characters that represents data stored in a specific memory location. Symbols optimize memory and can help programs run faster when performing comparisons or lookups.
A hash consists of unindexed key-value pairs. You may construct a hash in either of the following ways. Each will use symbols.
dog = {:name=>'Hamlet',:breed=>'Pug',:fav_food=>'pate'}cat = {name:'Simba',breed:'American Shorthair',fav_food:'Prosciutto'}dog[:name]=>'Hamlet'cat[:fav_food]=>'Prosciutto'
Mutator methods !
Mutator methods will not just return a value, but change the object they are called on to that value. Adding ! to certain ruby methods will turn them into their mutator method counterparts.
How to mutate an array
arr = [7,4,5]arr.sort#not a mutator method# => [4,5,7]arr# => [7,4,5]arr = [7,4,5]arr.sort!#the '!', aka a 'bang' will mutate the object# => [4,5,7]arr# => [4,5,7]
Typecasting
Typecasting is the act of altering an object's datatype
.to_i.to_s.to_a.to_f
Code blocks
Sometimes called closures in other languages is a chunk of contained code. Use curly braces, { } for single line blocks and do ... end for multiline blocks.
# count to 1010.times { puts"Hello" }x = 0until x >10doputs x x +=1end
String Interpolation
Allows one to inlcude a dynamic variable in a string. String interpolation can only be done on double-quoted strings.
team = 'Mariners'puts"Go #{team}!"# => "Go Mariners!"
Control flow
Conditionals
ifelsifelseunless
Loops
untilwhiletimesfor
Enumerables (similar to iterators)
eacheach_char # for stringseach_indexmapselectreduce
Examples
If/Else
course = "wdi"if course =="uxdi"puts"Hello, User Experience Designer!"elsif course =="fewd"puts"Hello, Front-End Developer"elsif course =="wdi"puts"Hello, Immersed Student"elseputs"Who are you?"end
Inline conditional
if heroic do_something_heroicend# is the same asdo_something_heroic if heroic ==true# is the same asdo_something_heroic if heroic
Loops
i = 0while i <5doputs"i is "+ i.to_s i +=1end# is the same asi = 0until i ==5doputs"i is "+ i.to_s i +=1end# is the same as5.timesdo|i|puts"i is #{i}"end# is the same asfor i in (0...5) doputs"i is "+ i.to_send# Will print out:# >i is 0# >i is 1# >i is 2# >i is 3# >i is 4
Iterating through Arrays
foods = ["carrots","kale","beets"]foods.eachdo|vegetable|puts"i like #{vegetable}"end# is the same asfor veg in ["carrots","kale","beets"] doputs"i like #{veg}"end# printing out indicesfoods.each_with_indexdo|vegetable, i|puts"i like #{vegetable}, #{i}"end# Will _each_ print out:# >i like carrots# >i like kale# >i like beets
Enumerables
foods = ['carrots','kale','beets']# map (similar to JS map)foods.mapdo|food| food *2end# => ["carrotscarrots", "kalekale", "beetsbeets"]# select (similar to JS filter)foods.selectdo|food| ['carrots','kale'].include?(food)end# => ["carrots", "kale"]# reduce (similar to JS reduce)numbers = [1,2,3,4]numbers.injectdo|a, b| a + bend# => 10# reduce with a starting valuenumbers.reduce(10) do|a, b| a + bend# reduce applying an operation/function via a symbolnumbers.reduce(:+)
Iterating through Hashes
car = {wheels:4,doors:2,seats:5}car.eachdo|key, num|puts"my car has #{num}#{key}"end# Will print out:# my car has 4 wheels# my car has 2 doors# my car has 5 seats
Functions
In Javascript
anonymous: function (param1, [..param2, [...]]){...},
named: function Name(param1, [..param2, [...]]){...}
uses lexical scope
used as values (functional programming)
require explicit return
all params are optional
In Ruby
uses def
does not capture scope
not used as values
implicitly returns last evaluation
optional parameters must be specified
Examples
defsay_helloputs"Hello, World!"endsay_hello()# is the same asdefsay_helloputs"Hello, World!"end# note missing parenthesessay_hello
In Ruby, leaving the () off of a function call is acceptable. Since functions can't be passed as values (i.e., aren't first-class), Ruby knows that we mean to call the function, so it calls it.
Parameters (Arguments)
defsay_hello(friend)puts"Hello, #{friend}!"endsay_hello("Tim")# is the same asdefsay_hello(friend)puts"Hello, #{friend}!"end# note the lack of parenthesessay_hello "Tim"# is the same asdefsay_hello(friend='Tim')puts"Hello, #{friend}!"end# note that there are no argumentssay_hello
Return Values
defadd(num1,num2)return num1 + num2endsum = add(2,3)puts"2 + 3 = #{sum}"# is the same asdefadd(num1,num2)# note the lack of explicit return num1 + num2endsum = add(2,3)puts"2 + 3 = #{sum}"
Ruby will automatically return the value of the last evaluated expression. This is called having "implicit returns". You are free to have an explicit return statement, but you don't have to.
Input / Output
You've already seen how puts will output information to the screen. What if we want to accept user input? Let's try gets.
puts"Enter your name:"you = getsputs"Enter a friend's name:"friend = getsputs"Hello, #{friend}. #{you} says hi."# Outputs# Enter your name:# Tim# Enter a friend's name:# Bob# Hello, Bob# . Tim# says hi.
puts"Enter your name:"you = gets.chompputs"Enter a friend's name:"friend = gets.chompputs"Hello, #{friend}. #{you} says hi."# Enter your name:# Tim# Enter a friend's name:# Frank# Hello, Frank. Tim says hi.
Much better. Now the unnecessary newlines are removed, thanks to chomp.