I’ve been fascinated with the ruby syntax for quite sometime now, and have been reading Mr. Neighborly’s Humble Little Ruby Book one of the most entertaining books I’ve found on Ruby. It is not meant to be an in-depth reference, instead it provides a no non-sense approach to learning the Ruby syntax and the Ruby way of life interlaced with a lot of humor.
This is part one of the notes I’ve taken as I went through the book. This is something I usually do when learning a new language, and I use it as sort of cheat sheet.
DISCLAIMER: These are the notes of a .NET Developer learning the Ruby language. These are the concepts as I understand them coming from a .NET background, and may not necessarily be correct.
STRINGS:
‘Hello, darling’ –> single quotes can only contain simple strings (no transformation)
"hello, darling \n \r" –> double quoted offer more escape sequences
"inches/yard: #{12*3}" –> inches/yard: 36
"#{"Tora! "*3}" –> Tora! Tora! Tora! . You can embed string definitions within other strings
NUMBERS:
-123456789 –> -123456789 # Fixnum
0d123456789 –> 1234567890 # Fixnum
1234323424231 –> 1234323424231 # Bignum
0x5C1 –> 1473 # Hex
01411 –> 777 # Octal
1_90_33 –> 19033 # Fixnum
-4.abs –> 4
6.zero? –> false
COLLECTIONS:
RANGE: Ranges hold a sequential collection of values, such as all numbers between 1 and 9 or the letters from A to Z. A range is created by placing a series of dots between the lower and upper limit
48..81 –> 48 to 81
48…81 –> 48 to 80
range === 49 –> true
range.include? 49 –> true
ARRAYS:
its_so_empty = []
oh_so_empty = Array.new
hello = ['ni hao', 'bonjour', 'hi', 'howdy']
random_types = [13, 'napkin', (1336 + 1).to_s]
%W (one two three) –> ["one", "two", "three"]
range.to_a –> Creates an array out of the range
my_array << 20 –> pushes 20 into the end of the array
my_array << 20 << 21 << 22 –> pushes 20 21 and 22 into the end of the array
my_array[0..2] –> [1, 2, 3]
my_array.at(0) –> 1
my_array.fetch(999, "Not found!!") –> "Not Found!!" . Second parameters returns if element if nil
my_array.values_at(0,1,2) –> [1, 2, 3]
my_array.pop –> removes the last element from the array
my_array.shift –> removes the first element from the array
my_array.delete_at(1) –> deletes item in position 1
my_array.delete(1) –> deletes item with value 1. Returns nil if not found
my_array.delete(1) { "Not Found" } –> deletes item with value 1 and returns "Not found" if the item was not found
HASH: Same as a dictionary with any kind of key and value
myhash = { ‘First’ => ‘This is first’, ‘Second’ => ‘This is second’ }
myhash = Hash.new("not here") –> Creates a hash and returns "not here" when a requested key does not exist
myhash['new key'] = "this is a new key" –> adds a new element to the hash
myhash.has_key?(‘first’) –> determines if the key is found
myhash.has_value?(‘value’) –> determins if he value is found
myhash.empty? –> true if empty
myhash.delete['first'] –> deletes the item with that name
myhash.clear –> clears the hash
myhash.to_a –> converts to an array of arrays
myhash.merge –> merges with another hash
myhash.replace –> replaces the elements of one hash with another
VARIABLES:
variable = 7 –> 7
variable = value = 7 –> 7
a, (b, c), d = 10, 11, 12, 13 –> a == 10, b == 11, c == nil, d == 12
variable += 1 –> variable = variable + 1
variable -= 1 –> variable = variable – 1
METHODS:
convention: methodname? with question mark at the end is used for querying an attribute i.e. France.has_military_victories? methodname! is changing the object that called the method i.e. bob_barker.set_age!(30)
def methodname(param1, param2)
#method body
end
def method(a = "this", b = "is", c = "fun")
#optional parameters by assigning a default value
end
def method(relation, *names)
#*names is a param array
end
return –> returns a value for the method. If no return element in the method the last value used is returned
return "more", "than", "one" –> returns more than one value
variable1, variable2, variable3 = return "more", "than", "one" –> assigns the return values in order to the variables
BLOCKS:
*A Block is like a method without a name* = Anonymous function
You can create a block like this:
{ |Parameter| code…. } i.e. myarray.each {|element| print "[" + element + "]…" }
do |parameter| code…. end i.e. myarray.each do |element| print "[" + element + "]…" end
PROCS:
myproc = Porc.new{|animal| puts "Ilove #{animal}!"}
myproc.call("pandas")
LAMBDAS:
myproc = lambda {|x| puts "Argument: #{x}"}
myproc.call("Texas forever!")
Diferences between Procs and Labdas:
– Labdas are strict on the number of arguments when calling
– Procs make the method that executes them return immediately. Lambda’s don’t yield gives control back to the caller before continuing. Perfect for loops that execute an anonymous function. If in a loop and you call yield inside the loop you can pass the item of the current iteration as an argument to yield, execute the caller code and return after the yield statement inside the loop when the caller is finished executing.
If you prepend a method parameter with & it makes that parameter a Proc automatically
Example:
def method(&block)
block.call
yield
end
method { print "I’m gettin’ called! " } –> I’m gettin’ called! I’m gettin’ called!
By using yield, you allow the calling statment to be executed again after the block.call
CLASSES:
class MyFirstClass < Object
#creates a class that inherits from object. Object inheretance is optional, this happens by default.
end
def initialize (optional parameters)
# this is the constructor
end
MyFirstClass.new –> creates the class
MyfirstClass.new(parameters) –> creates the class with a certain constructor
@variable –> These are class instance level variables. Private, not visible to the outside
self points to the current instance
Classes are never closed. You can add functionality to the string class for instance by simply adding this.
class String
def NewMethod
#same as extension methods in C#
end
end
Attributes / Properties:
#readonly property is just another method. Remember that the last value in a method is returned.
def prop1
@prop1
end
#read/write property
def prop1
@prop1
end
def prop1=(value)
@prop1=value
end
#how to write an automatic property. This simply creates the get and set definitions for prop1
attr_writer :prop1
attr_reader :prop1
#you can also do this. And vice versa for attr_reader.
attr_writer :prop1
def prop1
#do some processing before returning
newval = @prop1 + 1
newval
end
*attr_writer and attr_reader simply make it easier to defin a collection of automatic properties’ get and set methods
Scope:
When you add the protect keyword to the file in a new line, all the methods that come after it are marked protected, visible by self and derived classes only. You can change back to the the default (public) by adding public to a new line in the file. All methods after that will be public. Same with private.
class Myclass
protected # only self derived classes will have access to methods after this line
def protectedmethod1
end
def protectedmethod2
end
public # methods after this line are marked pubilc
def publicmethod1
end
def publicmethod2
end
private #methods after this line can only be accesed by self
def privatemethod1
end
def privatemethod2
end
end
Constants:
Simply add the variable directly underneath the class object.
class MyClass
CONSTANT_VARIABLE = "test"
def TestMethod
CONSTANT_VARIABLE
end
end
Class Methods (Static / Shared methods)
class MyClass
def MyClass.ClassMethod1
#this is method is a class wide method. available oustide the isntance class
end
end
Class Variables (Static / Shared fields)
Two @@ before the name make it a class wide field that lives outside of the instance class
class MyClass
def MyClass.ClassMethod1
#this is method is a class wide method. available oustide the isntance class
@@classfield1
end
end
Modules (Kind of like namespace, but better, more like on the fly inheritance / extension methods / partial classes all in one)
All you have to do is use include ModuleName to bring in the functionality of the module into your new class
module Movement
def run
puts "I’m running"
end
def walk
puts "I’m walking"
end
def crawl
puts "I’m so slowwww!"
end
end
class Man
include Movement
def jump
puts "I’m bipedal and I can jump like a fool!"
end
end
class Sloth
include Movement
def flop
puts "It’s all a lie…all I can do is flop around."
end
end
Files
You can bring in other files by adding using load or require. Diference is that require only loads it once. Load loads regardless if it has already been loaded. Require is more like signaling a reference need in case it has not already been preloaded.
load "libraries/myfile.rb"
require "/home/myaccount/code/libraries/myotherfile.rb"