#Ruby Monk Notes
##Ruby Primer
Objects and methods
#An argument to the method index, which finds the position of the argument in the array:
['rock','paper','scissors'].index('paper')
1
#The between? method here takes two arguments and determines if the number 2 lies between the numbers 1 and 3.
2.between?(1, 3)
String interpolation
#This method, given a String as the argument, inserts the length of that String into another String:
def string_length_interpolater(incoming_string)
"The string you just gave me has a length of #{incoming_string.length}"
end
string_length_interpolater("hello")
Search in a string
#It is conventional in Ruby to have '?' at the end of the method if that method returns only boolean values.
"[Luke:] I can’t believe it. [Yoda:] That is why you fail.".include?"Yoda"
"Ruby is a beautiful language".start_with?"Ruby"
"I can't work with any other language but Ruby".end_with?'Ruby'
#finds the index of the letter 'R'
"I am a Rubyist".index('R')
Splitting words
'Fear is the path to the dark side'.split
Replacing a substring
"I should look into your problem when I get time".sub('I','We')
#The method above only replaced the first occurrence of the term we were looking for. In order to replace all occurrences we can use a method called gsub which has a global scope...
"I should look into your problem when I get time".gsub('I','We')
#Replaces all the vowels with the number 1:
'RubyMonk'.gsub(/[aeiou]/,'1')
#Replace all the characters in capital case with number '0' in the following problem:
'RubyMonk Is Pretty Brilliant'.gsub(/[RMIPB]/, '0')
#Here is how you find the characters from a String which are next to a whitespace:
'RubyMonk Is Pretty Brilliant'.match(/ ./)
returns I
#This method just returns the first match rather than all the matches. In order to find further matches, we can pass a second argument to the match method. When the second parameter is present, it specifies the position in the string to begin the search. Let's find the second character in the string 'RubyMonk Is Pretty Brilliant' preceded by a space, which should be 'P'.
'RubyMonk Is Pretty Brilliant'.match(/ ./, 9)
returns P
The ternary operator
#In Ruby, ? and : can be used to mean "then" and "else" respectively. Here's the first example on this page re-written using a ternary operator.
def check_sign(number)
number > 0 ? "#{number} is positive" : "#{number} is negative"
end
###Arrays
Accessing arrays
[1, 2, 3, 4, 5][2] returns 3
Array indexes can also start from the end of the array, rather than the beginning! In Ruby, this is achieved by using negative numbers. This is called reverse index lookup. In this case, the values of the index start at -1 and become smaller.
[1, 2, 3, 4, 5][-5] returns the first value in the array, 1
Appending to an array
[1, 2, 3, 4, 5] << "woot" returns [1, 2, 3, 4, 5, "woot"]
[1, 2, 3, 4, 5].push "woot" does the same thing
Transforming arrays
[1, 2, 3, 4, 5].map { |i| i + 1 } returns [2, 3, 4, 5, 6]
The result is an entirely new array containing the results. In Ruby, the method map is used to transform the contents of an array according to a specified set of rules defined inside the code block.
Finding elements in an array
The method select is the standard Ruby idiom for filtering elements.
[1,2,3,4,5,6].select {|number| number % 2 == 0} returns [2, 4, 6]
--
names = ['rock', 'paper', 'scissors', 'lizard', 'spock']
names.select { |words| words.length > 5 == true } returns ["scissors", "lizard"]
Deleting elements from arrays
[1,3,5,4,6,7].delete 5 deletes the element 5 from the array
[1,2,3,4,5,6,7].delete_if{|i| i < 4 } returns 4 5 6 7
###Hashes
Hash example:
restaurant_menu = {
"Ramen" => 3,
"Dal Makhani" => 4,
"Tea" => 2
}
Accessing the values of keys:
restaurant_menu["Ramen"]
returns 3
Adding values to a hash:
restaurant_menu = {}
restaurant_menu["Dal Makhani"] = 4.5
restaurant_menu["Tea"] = 2
Iterating over a hash:
restaurant_menu = { "Ramen" => 3, "Dal Makhani" => 4, "Coffee" => 2 }
restaurant_menu.each do | item, price |
puts "#{item}: $#{price}"
end
Iteraring over a hash and changing its values:
#increases restaurant prices by 10%
restaurant_menu = { "Ramen" => 3, "Dal Makhani" => 4, "Coffee" => 2 }
restaurant_menu.each do |key, value|
restaurant_menu[key] = value + (value*0.1)
end
Returning keys or values as arrays:
Every Hash object has two methods: keys and values. The keys method returns an array of all the keys in the Hash. Similarly values returns an array of just the values.
Shortcuts for creating new hashes:
chuck_norris = Hash[:punch, 99, :kick, 98, :stops_bullets_with_hands, true]
p chuck_norris
###Classes
Looking up the class of any object:
puts 1.class
puts "".class
puts [].class
returns
Fixnum
String
Array
puts 1.is_a?(Integer)
puts 1.is_a?(String)
returns
true
false
What classes do:
-
Classes act as the factories that build objects.
-
An object built by a certain class is called 'an instance of that class.'
-
Typically, calling the new method on a class results in an instance being created.
-
A class needs a job or a role that its instances fulfill, or we have no reason to create one.
A class must have two features to justify its existence:
-
State: A class must have some kind of state that defines the attributes of its instances. In the case of a simple rectangle, this could simply be its length and breadth.
-
Behaviour: A class must also do something meaningful. This is achieved by the programmer adding methods to the class that interact with its state to give us meaningful results.
Building classes:
class Rectangle
def perimeter
2 * (@length + @breadth)
end
end
@length and @breadth are the "instance variables of the class".
This means that every instance of the class Rectangle will have its own unique copies of these variables and is in effect, a distinct rectangle.
In the example above, @length and @breadth don't have values yet, because we have no way to initialize them.
They are initialized in the example below:
class Rectangle
def initialize(length, breadth)
@length = length
@breadth = breadth
end
def perimeter
2 * (@length + @breadth)
end
def area
@length * @breadth
end
end
rect = Rectangle.new(2, 4)
rect.perimeter returns 12
rect.area returns 8
###Methods
Using return:
Be cautious when using return - calling return also exits the method at that point.
No code in the method after the return statement is executed.
def demonstrate_early_return
return
puts "You will never see this, because we never get here."
end
puts demonstrate_early_return.class
Good practice is to either avoid using return entirely or always use return in the last line of the method (which is effectively the same thing).
Methods with two or nore paramaters:
When a method has three parameters, but you only want to pass in two, you can set the third paramater to have a default value:
def add(a_number, another_number, yet_another_number = 0)
a_number + another_number + yet_another_number
end
puts add(1, 2)
The splat operator:
The splat operator allows you to create a method that can handle any number of parameters.
For example:
def add(*numbers)
numbers.inject(0) { |sum, number| sum + number }
end
puts add(1)
puts add(1, 2)
puts add(1, 2, 3)
puts add(1, 2, 3, 4)
The above returns:
1
3
6
10
In the above example, the splat operator converts a parameter list to an array.
It can also be used to convert arrays to parameter lists.
def add(a_number, another_number, yet_another_number)
a_number + another_number + yet_another_number
end
numbers_to_add = [1, 2, 3] # Without a splat, this is just one parameter
puts add(*numbers_to_add)
Another example of splatting:
def introduction(age, gender, *names)
"Meet #{names.join(' ')}, who's #{age} and #{gender}"
end
calling introduction(28, "Male", "Sidu", "Ponnappa", "Chonira") returns "Meet Sidu Ponnappa Chonira, who's 28 and Male
calling introduction(30, "Male", "Steven", "Deobald") returns "Meet Steven Deobald, who's 30 and Male"
calling introduction(38, "Indeterminate", "Therem", "Harth", "rem", "ir", "Estraven") returns "Meet Therem Harth rem ir Estraven, who's 38 and Indeterminate"
The above example accepts age and gender as parameters and the names as a splatted array. Names are concatenated using the Array#join method.
Optional parameters:
def add(a_number, another_number, options = {})
sum = a_number + another_number
sum = sum.abs if options[:absolute]
sum = sum.round(options[:precision]) if options[:round]
sum
end
puts add(1.0134, -5.568)
puts add(1.0134, -5.568, absolute: true)
puts add(1.0134, -5.568, absolute: true, round: true, precision: 2)
-4.5546
4.5546
4.55
The first invocation in the example above has two parameters, the second, three and the last, seemingly five.
In reality, the second and third invocations both have three parameters - two numbers and a hash.