Skip to content

Instantly share code, notes, and snippets.

@s-taylor
Created February 24, 2014 22:14
Show Gist options
  • Save s-taylor/9198327 to your computer and use it in GitHub Desktop.
Save s-taylor/9198327 to your computer and use it in GitHub Desktop.
Ruby Notes

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.

this is a comment!

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment