Current as at 25-Feb-2014
#Ruby Notes
###Terminology
Literals = values e.g. 1
or "Simon"
Variables = a place to store values
Operator = + - * / % =
Parameter = inputs for variables
Fix_num = an integer
###Assigning values to variables
example: x = value
x is our variable name
= is the assignment operator
||= is the conditional assignment operation, this only assigns the value if a value is not already assigned.
value is the data we wish to store in the variable e.g. 1 or "Simon"
###Arithmetic operators
*
= multiply
+
= addition
-
= subtraction
/
= division
%
= mod
x += y
(will add y to x)
x -= y
(will subtract y from x)
###Equality operators
x == y
- check if x equal to y (return true if they are same, false if they are not)
x != y
- check if x is not equalhash y (return false if they are the same, true if they are not)
x > y
- check if x greater than y
x < y
- check if x less than y
x >= y
- check if x greater than or equal to y
x <= y
- check if x less than or equal to y
###Logical operators
&&
= AND
||
= OR
!true
== false
!false
== true
Details for AND...
true && true
# => true
true && false
# => false
false && true
# => false
false && false
# => false
Details for OR...
true || true
# => true
true || false
# => true
false || true
# => true
false || false
# => false
Note: when using OR if the first expression evaluates to true, ruby will not run / check the second expression as the result will be true regardless.
###Combined comparison operator
value1 <=> value2
returns 1 if value1 should come after value2
returns 0 if equal
returns -1 if value1 should come before value2
Note: can be used to compare text values
###Comments You can use # to comment a line.
Or you can use '=begin' and '=end' e.g.
=begin
I'm a comment!
I don't need any # symbols.
=end
###Interactive ruby shell
How to launch?
type "irb" in terminal
How to display the class?
x.class
How to list the inbuilt methods?
x.methods
clear the terminal window
command + k
list local variables
local_variables
Add to a string
string1 + string2
quit irb
quit
return the last value returned
Use "_" (underscore)
You can store this in a var using "my_var = _"
###Methods brackets in ruby methods are optional, you can just use a space and comma seperate your parameters. The only time brackets are required is when you nest a method inside another method.
This is OK
multiply 2, 2
But this is not OK
multiply multiply 2, 2, 2
You need to do…
multiply(multiply(2,2),2)
####Method Syntax
def method_name(para) <enter>
yourcode
yourcode
end
by default, if you do not specify what to return, it will return the last variable used in your method
####Splat Methods This allows you to handle an unknown number of arguements in your method
def what_up(greeting, *bros)
bros.each { |bro| puts "#{greeting}, #{bro}!" }
end
what_up("What up", "Justin", "Ben", "Kevin Sorbo")
####Optional Parameters in Methods
def alphabetize(arr, rev=false)
your code here...
end
This defaults the 'rev' parameter to false if not passed.
###! in Methods Most methods have two versions, one with a "!" and one without. When using the version without, this will simply return the result of the method. When using the version with "!", this will return the value AND update the variable with the returned value where it is stored.
###? in Methods indicates the return value will be a boolean
###Object Methods
.methods
= list all methods of the object
.class
= tells you the class of an object
.dup
= create a new instance of the object so original instance is unaffected
.respond_to?(:xxx)
= takes a key input and this will return true if a method exists on the object with that name or false if it does not.
.is_a? xxxxx
= checks if value is an Integer, Symbol, String etc... you must capitalize the input!
###String Methods
.length
= the number of chars in the string
.upcase
= convert to uppercase
.downcase
= convert to lowercase
.capitalise
= sets the first letter in the string to a capital (does not do every word!)
.include? "x"
= returns true if x can be found within string
.sub "x", "y"
= replaces the first occurence of "x" with "y"
.gsub "x", "y"
= replaces all occurences of "x" with "y"
.reverse
= reverse the text in the string
.split(" ")
= returns an array of strings seperating the input string by " "
.to_sym
OR .intern
= convert to a symbol
.concat("text")
= add 'text' to the end of the current string
add a string to the end of another string…
"Simon" << "Taylor" == "Simon Taylor"
Note: This is much more efficient than using '+' from a memory management perspective as this does not create a new object
####Regular Expressions
These can be input in methods by using a forward slash at the start and end
'RubyMonk Is Pretty Brilliant'.gsub(/[A-Z]/,'0')
Will return...
0uby0onk 0s 0retty 0rilliant
All capital letters are converted to 0's
###Integer Methods
.next1
= will return the next number following the specified value
e.g. 4.next == 5
###Float Methods
.abs
= convert to an absolute number
###String Interpolation Rather than concatenating strings, you can insert ruby code into your strings e.g if you have…
age = 29
name = "Simon Taylor"
puts "Hi there, my name is #{name} and I am #{age} years old"
Note: If you use interpolation you do not need to convert variables to strings
Note 2: You must use double quote and not single quote for Interpolation!
###True
Ruby will consider anything that is not nil or false to be true.
This can cause errors easily as if you do…
x = 8
if (x = 10)
puts "it equals 10!"
end
The result will be that it does print, as x = 10 is setting x = 10 (we didn't use ==) and 10 is considered true since its not nil or false!
###Return in Functions By default Ruby will always return the last variable in a function, there is generally no need to define what is returned.
###Gets
gets
- This can be used to prompt the user for input in the terminal.
Note: When using this, when the user presses enter to submit their input the carriage return is captured as part of their input. To remove this just use gets.chomp
###Puts
puts "x"
- this will print x to the console with a line break at the end
print "x"
- this will print x to the console with no line break
Note: puts returns nil unless there is an error
###If Statement Syntax
if category == 'cats'
votes = votes * 5
elsif category == 'bacon'
votes = votes * 8
elsif category == 'food'
votes = votes * 3
else
votes = 0
end
note: You do not need to use 'then' unless you are typing your statement on one line
####Single line If yourcode if boolean
puts "three" if x == 3
Note: this syntax does not require an 'end'
####Single line If with else (Ternary)
x == 3 ? puts "three" : puts "not three"
###Unless
unless hungry
puts "I'm writing Ruby programs!"
else
puts "Time to eat!"
end
####Single line Unless
yourcode unless boolean
###Case Statement
case category
when 'cats'
votes = votes * 5
when 'bacon'
votes = votes * 8
when 'food'
votes = votes * 3
end
Note: the when segments can be written on a single line if you include 'then'
####Case statements with multiple conditions
case
when x > 1 && y ="a"
do something
when x < 1 && y ="b"
do something else
else
do something else different
end
###Do loops example
1.upto(10) do |x|
puts x
end
1 = is the start point of our loop
.upto10 = tells the loop to increment by 1 and finish at 10
|x| = stores the current loop value
end = end the loop
alternatively you can use .downto(x)
####Times Loop
3.times do
puts "yay!"
end
This will print "yay!" 3 times
####Alternative to 'do' & 'end'
do ..... end can be replaced with { ..... }
This is cleaner if you wish to write on a single line.
####For Loop
for num in 1...10
puts num
end
Note: Using 3 full stops results in the final number being excluded from the loop (10 in this case). Using 2 full stops will include the final number in the counter.
###Conditional Loops #####While Loop
count = 10
while count > 0
puts "Looping"
count -=1
end
#####Until Loop
count = 10
until count < 1
puts "Looping"
count -= 1
end
#####Do Loop
count = 10
loop do
break if count < 1
puts "Looping"
count -= 1
end
Note: you can use the 'next' key word, to skip executing the current code and move to the next repeat of the loop
###Loop through an Array
array.each do |value|
puts value
end
OR
array.each_with_index do |value,index|
puts "I'm up to object #{index + 1}"
puts value
end
###Arrays example:
states = ["NSW","TAS","VIC","SA","WA","NT","ACT","QLD"]
index 0,1,2,3,4,5,6,7,8
therefore states[3] would return "SA" as 0 is the first index position
to quickly create an array of words you can use "%w(text text text)" where spaces are treated as new array values.
states = %w(NSW VIC TAS SA WA QLD ACT NT)
create an empty array with either []
OR Array.new
.length
OR .count
OR .size
OR .nitems
= will tell us how many values in the array
.sort
= will order the array
.reverse
= reverse the ordering of items in the array
.first
= will return the first value
.last
= will return the last value
.shuffle
= randomise an array
.empty?
= return if the array is empty (true / false)
.push(x)
= adds a new value onto the end of the array
.pop
= removes the last value from an array and returns a string
.unshift(x)
= adds a new value onto the start of the array
.shift
= removes the first value from an array and returns a string
.index(value)
= will return the index of a value if found in the array
.insert(x,value)
= will insert the value at position x and move values from x onwards down one position
.uniq
= return only unique values from the array
.compact
= removes nil values from the array
.join(x) = combines all values in array and returns a string. Optionally with x in between values.
.clear
= purge all values in the array
.delete(x)
= deletes all elements with the value of x
.delete_at(x)
= deletes the element at position x (remember 0 is first position)
.collect { |x| your_code_here }
this will apply your code on each item in the array and then return a new array with the results of each modified value e.g.
fibs = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
doubled_fibs = fibs.collect {|num| num * 2}
#[2, 2, 4, 6, 10, 16, 26, 42, 68, 110]
my_array[-1] = will return the last value in the array
add a value to the end of the array… my_array << "new value"
###Looping through Arrays
arrayname.each do |x|
puts x
end
###Multidimensional Arrays
xox [
["x","o","x"],
[nil,"o",nil],
["x",nil,nil],
]
Will return row 2, column 1
xox[2][1]
###Hashes What is a Hash? Effectively a lookup table. It is similar to an array except instead of looking up a value by an index we perform the lookup via a key. It is essentially a collection of key value pairs.
Define a Hash
States = {:nsw => "New South Wales", :vic => "Victoria"}
Note: In this case the ":nsw" and ":vic" are a symbol! But you can use a string instead. Symbols cannot be changed and all references to the same symbol refer to the same object. Where as two strings with the same value are still seperate objects! Can save significantly on memory allocation.
Lookup a Value from a Hash
States[:nsw] #this will return "NSW"
How to add a value to a Hash
books["Gravity's Rainbow"] = :splendid
Create an empty Hash
my_hash = Hash.new
(must be in caps)
Print out all keys and values in a hash
my_hash.each do |key, value|
puts "#{key}: #{value}"
end
Sort a Hash
my_hash = my_hash.sort_by { |key, value| value}
...and if you want this in reverse order then use...
my_hash.reverse!
Alternative Syntax
States = {nsw: "New South Wales", vic: "Victoria", etc…}
This is not recommended however as there are instances where you must refer to a key as :key. So if you are searching your code you'd need to search for ":key" and "key:" to find all instances where it is used.
###Hash Methods
.select (return a selection of values based on set criteria)
movie_ratings = {
memento: 3,
primer: 3.5,
the_matrix: 3,
truman_show: 2,
uhf: 1,
lion_king: 3.5
}
good_movies = movie_ratings.select do |k,v|
v > 3
end
each_key (look through keys only)
my_hash.each_key { |k| puts k.to_s }
each_value (loop through values only)
my_hash.each_key { |v| puts v }
.delete(key)
deletes the associated key value pair from the hash
.keys
= lists all keys
.values
= list all values
###Blocks / Yield
A block is essentially a piece of code that you define that is run at a certain point within a method. The method can also pass parameters to the block for use in your code. The place in which the block code run is where you position the 'yield' command. e.g.
def yield_name(name)
puts "In the method! Let's yield."
yield name
puts "Block complete! Back in the method."
end
yield_name("Simon") { |name| puts "My name is #{name}." }
If the code is looping (i.e. each) the block may be run many times.
####Procs Blocks are not objects and therefore cannot be saved for reuse. Procs are the solution to this and effectively save the block code within an object.
multiples_of_3 = Proc.new do |n|
n % 3 == 0
end
(1..100).to_a.select(&multiples_of_3)
The "&" is used to convert the proc into a block.
Note: Your method must then use brackets and not { }!!!
####Lambdas Very similar to a Proc...
strings = ["leonardo", "donatello", "raphael", "michaelangelo"]
symbolize = lambda { |x| x.to_sym }
symbols = strings.collect(&symbolize)
#####Lambdas vs Procs A lambda checks the number of arguments passed to it, while a proc does not. This means that a lambda will throw an error if you pass it the wrong number of arguments, whereas a proc will ignore unexpected arguments and assign nil to any that are missing.
Second, when a lambda returns, it passes control back to the calling method; when a proc returns, it does so immediately, without going back to the calling method (the method exits).
###Rest-client Mashable excercise
navigate to the folder you wish to install the gem
type "gem install rest-client"
type "require rest-client"
type "response = RestClient.get [url]"
type "require 'json'"
type "response_hash = JSON.parse(response)"
From here you can access response_hash as a Ruby hash
###Classes ####Defining a Class
class Chair
_your code for attributes and methods_
end
(class names should always start with a capital letter)
To add attributes and behaviour to a class, we use instance_variables and instance_methods.
####Instance Variables
To define an instance variable you need to start the variable name with an @ symbol. This variable will then persist for the object, even if its defined inside a method for that object
e.g.
class Chair
@legs = 4
end
####Creating an object of that Class Creating an object is creating an 'instance' of a class
my_chair = Chair.new
####Setters A Setter method will 'set' the attributes of an object
class Chair
def legs=(val)
@legs = val
end
end
The difference between a setter and a standard method, is that you can then use the assignment operator to pass a value to this method. Using the above example you can use…
my_chair = Chair.new
my_chair.legs = 4
####Getters A Getter will return the attributes of an object
class Chair
def legs
@legs
end
end
####The shortcut for Getters
class Chair
attr_reader :legs #creates a setter
attr_writer :legs #creates a getter
end
OR
class Chair
attr_accessor :legs
end
You can even create multiple attributes at one time
e.g. attr_accessor :legs, :colour
####Initialize Method This allows you to pass in the attributes as you create the instance of the object
class Chair
def initialize(legs, colour)
@legs = legs
@colour = colour
end
end
Chair.new(3,"White")
To make parameters non mandatory you MUST set a default value, you can do this using =default inside the method input section e.g.
class Chair
def initialize(legs=4, colour="White")
@legs = legs
@colour = colour
end
end
OR a better way to code this is…
class Book
def initialize(attr={})
@title = attr[:title]
@author = attr[:author]
end
end
Book.new(:title => "Harry Potter", :author => "J K Rowling")
This allows parameters to be optional by passing in a hash
####Class Methods These are defined using the class_name.method_name e.g.
def Computer.create_user
do something
end
####Public vs Private Methods Methods are public by default, howevere if you need to make this clear you can specify this in your code...
class ClassName
# Some class stuff
public
# Public methods go here
def public_method; end
private
# Private methods go here
def private_method; end
end
####Self
You can use self.x
which will allow you to refer to instance_variables or methods
####Puts class_instance
This is the same as doing puts class_instance.to_s
To define meaningful output it is a good idea to define a to_s
method on your class
###Require
This allows you to access classes in a separate .rb file
e.g. require 'filename'
These files must be in your $LOAD_PATH, you can type in $LOAD_PATH in irb
require_relative allows you to reference files in the same folder (instead of the LOAD_PATH)
e.g. require_relative lib/my_code
Note: you do not need to do .rb for a file extension, it assumes .rb because we're using ruby. In above example it would look for my_code.rb
The convention is to only have ONE class per file.
###Gems
Install a gem using
gem install [gem-name]
Uninstall a gem using
gem uninstall [gem-name]
Get a list of installed Gems using
gem query --local
###Debugger
gem install debugger
require 'debugger'; debugger
###Inheritance define a super class
class furniture
attr_accessor :name, :qty
def take_from_stock(x)
@qty -= x
end
end
class chair < furniture
end
class table < furniture attr_accessor :seats_x end
###Modules You can think of a module as a toolbox that contains a set methods and constants. Modules can't create instances and can't have subclasses. They're just used to store things!
It doesn't make sense to include variables in modules, since variables (by definition) change (or vary). Constants, however, are supposed to always stay the same, so including helpful constants in modules is a great idea. Ruby constants are written in ALL_CAPS and are separated with underscores if there's more than one word.
Also note that because modules can't be instantiated, we can't just use def some_name. That will make an instance method! Instead, we'll want to create methods at the class/module level. We can do this explicity (using the same syntax as a class method) or using def self.method_name.
module Circle
PI = 3.141592653589793
def Circle.area(radius)
PI * radius**2
end
def Circle.circumference(radius)
2 * PI * radius
end
end
####Includes You would use inheritance where there is a clear heirachy, where objects are different types of the same thing. Where there is a shared behaviour (methods) across two different things you might 'mix in' a module.
Use the word include module_name
inside your class definition.
When we include a module that has already been required, we pull in all its methods and constants at the instance level. That means that any class that includes a certain module can create objects (instances) that can use those very same methods!
Note: You can only ever have one super class for a class but you can use multiple modules.
module Action
def jump
@distance = rand(4) + 2
puts "I jumped forward #{@distance} feet!"
end
end
class Rabbit
include Action
attr_reader :name
def initialize(name)
@name = name
end
end
class Cricket
include Action
attr_reader :name
def initialize(name)
@name = name
end
end
peter = Rabbit.new("Peter")
jiminy = Cricket.new("Jiminy")
peter.jump
jiminy.jump
###Namespacing
One of the main purposes of modules is to separate methods and constants into named spaces. This is called (conveniently enough) namespacing, and it's how Ruby doesn't confuse Math::PI
and Circle::PI
.
See that double colon we just used? That's called the scope resolution operator, which is a fancy way of saying it tells Ruby where you're looking for a specific bit of code. If we say Math::PI
, Ruby knows to look inside the Math module to get that PI.