Ruby deep concepts with examples for serious ruby developers

Recently I have read a book name "Ruby Deep Dive" written by Jesus Castello. He is the founder of Rubyguides. I had to spend around 4 days to read the whole book with exercise. To read a book from the computer it's so much hard for me. On my Samsung Tab I use Moonreader as pdf reader with dropbox synchronisation that I can read also from mobile. Instead of wasting physical papers I use Ziteboard app with Baseus stylus pen. I dislike to always compile on the computer, to compile on mobile I use Ruby Compiler. For reading a book and as well as practising I like to set two app split or popup mode on android. Using App usages I get exact time how much time spend on reading.

I tried to note down when I was reading the book. Also collected examples from different sources which one is the best to understand the concepts. I believe you already know Ruby. You can read this article like a cheatsheet. 


Enumerable: 

each: Passes each element of the collection to the given block. Returns the object itself without modification.

foo = [3,4,5]
foo.each do |value|
  puts value
end

#=> 3 4 5

each_cons: Creates sub-arrays of size n. Each sub-array is made from n consecutive elements, advancing one position at a time.

foo = (1.. 5)
 
foo.each_cons(2){|item| p item}

#=> [1, 2] [2, 3] [3, 4] [4, 5]


inject / reduce: Yields the current element and an accumulator variable. Order: sum, element 

[10,20,30,40,50].inject() do |total, num|
  puts "Total: #{total}".ljust(12) + "Number: #{num}"
  total + num
end

#=> Total: 10 Number: 20
#=> Total: 30 Number: 30
#=> Total: 60 Number: 40
#=> Total: 100 Number: 50
[10,20,30].inject(&:+)
#=> 60


each_with_object: Very similar to inject, doesn't require returning the accumulator variable. Order: element, sum.

array = ["John", "Joe", "Marcel", "John", "AJ", "Marcel", "John"]

result = array.each_with_object(Hash.new(0)) do |element, hash|
hash[element] += 1
end

puts result

#=> { "John"=>3, "Joe"=>1, "Marcel"=>2, "AJ"=>1 }


each_slice: Breaks an array into sub-arrays of size n. map / collect Returns a new array with the elements returned by the block.

['A', 'B', 'C', 'D'].each_slice(2).to_a[0]

#=> ["A", "B"]


min: Returns the smallest element

[5, 10].min
# 5


partition: Returns a 2d array, where the first array contains the elements that match the condition and the second array contains the elements that didn't match the condition, Returns the smallest element. Uses a block to define what data should be used to compare between the elements.

numbers = [1,2,3,4,5]
p numbers.partition(&:even?)

#=> [[2, 4], [1, 3, 5]]


group_by: Returns a hash where the keys are the evaluated result from the block and the values are the elements that correspond to that key.

country_list = ["Afghanistan","Brazil","Botswana","Argentina"]

country_list.group_by { |country_name| country_name[0].to_sym }

#=> {:A=> ["Afghanistan", "Argentina"], :B=> ["Brazil", "Botswana"]


max: Returns the biggest element select / find_all Returns all the elements that match a condition

[5, 10].max
# 10

max_by:
Returns the biggest element. Uses a block to define what data should be used to compare between the elements. reject Returns all the elements that don't match a condition,
a = ["gopal", "tunday", "geeks", "classes", "linux"]

p a.max_by(2) {|obj| obj.length }
p a.max_by {|obj| obj.length }


["classes", "tunday"]
"classes"


sort: Returns an array with elements sorted according to their own <=> method. method. 

numbers = [5,3,2,1]
numbers.sort

# [1,2,3,5]


any? Returns true if any the elements match a condition.

[1,2,3].any? { |n| n > 0 }
# true


sort_by: Like sort, but uses the value returned by the block as the value to be sorted. all? Returns true if all the elements match a condition.

[48,75,19,12,21].sort_by { |n| n.to_s[-1] }

#=> [21, 12, 75, 48, 19]


Zip: Creates a new 2d Array that is formed from the elements of obji & obj2. One element from each side is picked in every iteration to form one of the subarrays. 

[1,2,3].zip ([4,5,6])

#=> [[1,4], [2, 5), (3, 6]]


none? Returns true if none of the elements match a condition.

numbers = [10, 19, 18]
result1 = numbers.none? { |num| num>4}
puts result1

result2 = numbers.none? { |num| num>=20}
puts result1

#output
=> false
=> true

 

take: Return the first n elements.
num = [2, 3, 4, 5]
puts num.take(3)

#=> 2 3 4 


one? Return true if exactly one element matches a condition.

["a"].one?
# true

[].one?
# false

[nil].one?
# false


reverse_each: Just like each but in reverse order

a = [ "a", "b", "c" ]
a.reverse_each {|x| print x, " " }

#=> c b a


count: Returns a count of how many times the block evaluates to true.

num = [2,3,4]
puts num.count

#=> 3


cycle: Repeats ALL the elements n times, so if you do [1,2].cycle(2) you would have (1,2,1,2] would have [1,2,1,2]

a = ["a", "b", "c"]

a.cycle { |x| puts x }
#=> a, b, c, a, b, c,.. forever.

a.cycle(2) { |x| puts x }
#=> a, b, c, a, b, c.


find: Returns the first element that matches a condition

numbers = (1..50)
numbers.find { |num| num % 2 == 0 && num % 9 == 0}

#=> 18


grep: Returns an array of every matching element where Pattern === element. Example: [1,2,3].grep(Integer). Also please check this example.

objects = ["a", "b", "c", 1, 2, 3, nil]

objects.grep(String)
# ["a", "b", "c"]

objects.grep(Integer)
# [1, 2, 3]
fruit = ["apple", "orange", "banana"]
fruit.grep(/^a/)

# ["apple"]

each_with_index: Like each but this gives you the current index as the second argument for your block

[:foo, :bar, :baz].each_with_index do |value, index|
puts "#{index}: #{value}"
end

Output =>
0: foo
1: bar
2: baz


Array:

Return: Return the value at the given index.

shift / unshift: Add & remove values from the start of the array.

a = [18, 22, 33, nil, 5, 6]
a.unshift(2)
#=> [2, 18, 22, 33, nil, 5, 6]
c = [18, 22, 50, 6]
c.unshift(22)
#=> [22, 18, 22, 50, 6]

 

bsearch: Uses the binary search algorithm & a block to find a value in the array. Assumes that the array is sorted.

a = [0, 4, 7, 10, 12]

a.bsearch {|x| x >= 4 } # => 4
a.bsearch {|x| x >= 6 } # => 7
a.bsearch {|x| x >= -1 } # => 0
a.bsearch {|x| x >= 100 } # => nil

push / pop: Add & remove values from the end of the array. 

first_arr = ["Letters", "a", "b"]
first_arr.push("c","d")

#=> ["Letters", "a", "b", "c", "d"]
a = [1,2,3,4]
a.pop #4
a.pop(2) # [3,4]
a.pop(3) # [2,3,4]

reverse: Returns a new array which is reversed.

[ "a", "b", "c" ].reverse #=> ["c", "b", "a"]
[ 1 ].reverse #=> [1]

 

join: Returns an string which is a concatenation of all the array values. Takes an optional argument used to specify a separator character.

[ "a", "b", "c" ].join #=> "abc"
[ "a", "b", "c" ].join("-") #=> "a-b-c"

 

sample: Returns a random value from the array. Takes an argument which lets you specify how many unique random values do you want.

a = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
a.sample #=> 7
a.sample(4) #=> [6, 4, 2, 5]

index: Returns the index of the value you pass in as an argument, returns nil if not found.

a = [ "a", "b", "c" ]

a.index("b") #=> 1
a.index("z") #=> nil
a.index { |x| x == "b" } #=> 1

rotate: Rotates the array values X positions to the left.

a = [ "a", "b", "c", "d" ]

a.rotate #=> ["b", "c", "d", "a"]
a #=> ["a", "b", "c", "d"]
a.rotate(2) #=> ["c", "d", "a", "b"]
a.rotate(-3) #=> ["b", "c", "d", "a"]

 

include? Returns true if the value is found in the array. Doesn't work for values nested inside other objects / arrays.

a = [ "a", "b", "c" ]

a.include?("b") #=> true
a.include?("z") #=> false

transpose: Switch the columns into rows in a multi-dimensional array.

a = [[1,2], [3,4], [5,6]]
a.transpose #=> [[1, 3, 5], [2, 4, 6]]

insert: Insert a new element at the given position. Takes two arguments: index & element to add.

"abcd".insert(0, 'X') #=> "Xabcd"
"abcd".insert(3, 'X') #=> "abcXd"
"abcd".insert(4, 'X') #=> "abcdX"
"abcd".insert(-3, 'X') #=> "abXcd"
"abcd".insert(-1, 'X') #=> "abcdX"

clear: Empty the array.

set = Set[1, 'c', :s] #=> #<Set: {1, "c", :s}>
set.clear #=> #<Set: {}>
set #=> #<Set: {}>

first: Returns the first value of the array. Takes an optional argument which lets you specify how many values to return.

a = [ "q", "r", "s", "t" ]
a.first #=> "q"
a.first(2) #=> ["q", "r"]

uniq: Returns a new array where all the values only appear one time. Consider using a Set if you need to do use this method often.

a = [ "a", "a", "b", "b", "c" ]
a.uniq # => ["a", "b", "c"]

flatten: Returns a new array which has any nesting removed. So a 2d array becomes a regular array.

s = [ 1, 2, 3 ] #=> [1, 2, 3]
t = [ 4, 5, 6, [7, 8] ] #=> [4, 5, 6, [7, 8]]
a = [ s, t, 9, 10 ] #=> [[1, 2, 3], [4, 5, 6, [7, 8]], 9, 10]

a.flatten #=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
a = [ 1, 2, [3, [4, 5] ] ]

a.flatten(1) #=> [1, 2, 3, [4, 5]]

compact / compact! Remove any nil values.

[ "a", nil, "b", nil, "c" ].compact! #=> [ "a", "b", "c" ]
[ "a", "b", "c" ].compact! #=> nil


fill: Modify the array by replacing the next X values (third parameter) starting at index Y (second parameter) with the given string (first parameter). It will insert additional values if the position is empty. Example: ['a', 'a', 'a').fill('b', 1, 2)

a = [ "a", "b", "c", "d" ]
a.fill("x") #=> ["x", "x", "x", "x"]
a.fill("z", 2, 2) #=> ["x", "x", "z", "z"]
a.fill("y", 0..1) #=> ["y", "y", "z", "z"]
a.fill { |i| i*i } #=> [0, 1, 4, 9]
a.fill(-2) { |i| i*i*i } #=> [0, 1, 8, 27]


concat: Concatenate the second array into the first one.

[ "a", "b" ].concat( ["c", "d"] ) #=> [ "a", "b", "c", "d" ]
[ "a" ].concat( ["b"], ["c", "d"] ) #=> [ "a", "b", "c", "d" ]
[ "a" ].concat #=> [ "a" ]

fetch: Returns the value at the given index. Raises an IndexError exception if the index is out of bounds.

h = { "a" => 100, "b" => 200 }
h.fetch("a") #=> 100
h.fetch("z", "go fish") #=> "go fish"
h.fetch("z") { |el| "go fish, #{el}"} #=> "go fish, z"
h = { "a" => 100, "b" => 200 }
h.fetch("z")

#=> output
prog.rb:2:in `fetch': key not found (KeyError)
from prog.rb:2

cycle: Repeats the whole array the given number of times.

a = ["a", "b", "c"]
a.cycle { |x| puts x } # print, a, b, c, a, b, c,.. forever.
a.cycle(2) { |x| puts x } # print, a, b, c, a, b, c.

empty? Returns true if the array length is 0.

[].empty? #=> true
[1].empty? #=> false

delete: Finds & deletes a value. Returns the deleted value (nil if not found).

h = { "a" => 100, "b" => 200 }
h.delete("a") #=> 100
h.delete("z") #=> nil
h.delete("z") { |el| "#{el} not found" } #=> "z not found"


delete_at: Delete the value at this index.

a = ["ant", "bat", "cat", "dog"]
a.delete_at(2) #=> "cat"
a #=> ["ant", "bat", "dog"]
a.delete_at(99) #=> nil

drop_while: Iterates over the array, discarding all the values that don't match a condition. If the condition is met the remaining values are returned.

a = [1, 2, 3, 4, 5, 0]
a.drop_while {|i| i < 3 } #=> [3, 4, 5, 0]

delete_if: Delete the values that match a condition.

scores = [ 97, 42, 75 ]
scores.delete_if {|score| score < 80 } #=> [97]


Block:

yield: Used inside a method to call the passed block. It can be called multiple times. You can use "block_given?" to check if a block was passed to the method.

def print_once
yield
end

print_once { puts "Block is being run" }

=> Block is being run
def print_twice
  yield
  yield
end
print_twice { puts "Hello" }
# "Hello"
# "Hello"

def do_something_with_block
return "No block given" unless block_given?
yield
end

Lambdas: It behaves more like a real method. 

say_something = -> { puts "This is a lambda" }


Explicit Blocks: Methods don't need an argument in the method definition to be able to accept a block, so they are implicit by default. Explicit blocks allow you to save & name the block.

def explicit_block(&block)
block.call # same as yield
end

explicit_block { puts "Explicit block called" }

Implicit Blocks:  To create an explicit block you add a new argument to your method definition, it must be the last argument & it should start with the ampersand symbol (like this -> &block).

Symbol#to_proc: Helps you call a method on all the elements of a collection without the full block syntax. Example: ['a', 'b', 'c'].map(&:size)



Hash:

Hash: 

{ a: 1, b: 2, c: 3 }
fruits = { coconut: 1, apple: 2, banana: 3 }

fruits[:orange] = 4

 

fetch: Returns a value associated with a key. Raises a keyError exception if the key is not found. Can take a default value via the second parameter or as a block.

fruits = { coconut: 1, apple: 2, banana: 3 }
fruits.fetch(:peach, 0)

default: Returns the default value for this hash object.

each_key: Iterate over all the existing keys.

h = { "a" => 100, "b" => 200 } h.each_key {|key| puts key }

#=> Output
a b

 

default_proc: Returns the default proc for this hash object.

h = Hash.new {|h,k| h[k] = k*k } #=> {}
p = h.default_proc #=> #<Proc:0x401b3d08@-:1>
a = [] #=> []
p.call(a, 2)

a #=> [nil, nil, 4]

each_value: Iterate over all values.

h = { "a" => 100, "b" => 200 }
h.each_value {|value| puts value }

#=> output

100
200

default =  Sets the default value for this hash. Can also be set on initialization as a parameter for new. Example: Hash.new(0)

keys: Returns an array with all the hash keys.

default_proc= Sets the default proc for this hash, which is called when a key doesn't exist. Can also be set on initialization as a block. Example: Hash.new { [hash, key hash[key] = 0 )

values: Returns an array with all the hash values.

dig: Used to navigate nested hash structures.

h = { foo: {bar: {baz: 1}}}
h.dig(:foo, :bar, :baz) #=> 1
h.dig(:foo, :zot, :xyz) #=> nil
g = { foo: [10, 11, 12] }
g.dig(:foo, 1) #=> 11
g.dig(:foo, 1, 0) #=> TypeError: Integer does not have #dig method
g.dig(:foo, :bar) #=> TypeError: no implicit conversion of Symbol into Integer

merge: Merges two hashes together, returning a new hash. Newer values (second hash) overwrite old ones.

h1 = { "a" => 100, "b" => 200 }
h2 = { "b" => 254, "c" => 300 }
h1.merge(h2) #=> {"a"=>100, "b"=>254, "c"=>300}
h1.merge(h2){|key, oldval, newval| newval - oldval}
#=> {"a"=>100, "b"=>54, "c"=>300}
h1 #=> {"a"=>100, "b"=>200}

 

value? Returns true if the value exists.

update / merge! Like merge, but modify the original hash in place.

h1 = { "a" => 100, "b" => 200 }
h2 = { "b" => 254, "c" => 300 }
h1.merge!(h2) #=> {"a"=>100, "b"=>254, "c"=>300}
h1 #=> {"a"=>100, "b"=>254, "c"=>300}

h1 = { "a" => 100, "b" => 200 }
h2 = { "b" => 254, "c" => 300 }
h1.merge!(h2) { |key, v1, v2| v1 }
#=> {"a"=>100, "b"=>200, "c"=>300}

h1 #=> {"a"=>100, "b"=>200, "c"=>300}

key? Returns true if the key exists.

delete: Given a hash key, this method removes a key/value pair from the hash & returns the value. Returns the default value if the key is not found.

h = { "a" => 100, "b" => 200 }
h.delete("a") #=> 100
h.delete("z") #=> nil
h.delete("z") { |el| "#{el} not found" } #=> "z not found"

length / size: Returns the number of key/value pairs in the hash table.

h = { "d" => 100, "a" => 200, "v" => 300, "e" => 400 }
h.length #=> 4
h.delete("a") #=> 200
h.length #=> 3

store: Stores a key-value pair in the hash table.

h = { "a" => 100, "b" => 200 }
h["a"] = 9
h["c"] = 4
h #=> {"a"=>9, "b"=>200, "c"=>4}

h.store("d", 42) #=> 42
h #=> {"a"=>9, "b"=>200, "c"=>4, "d"=>42}

invert: Invert the keys & values, so the keys become the new values and the values become the new keys.

h = { "n" => 100, "m" => 100, "y" => 300, "d" => 200, "a" => 0 }
h.invert #=> {0=>"a", 100=>"m", 200=>"d", 300=>"y"}

clear: Empty the hash.

h = { "a" => 100, "b" => 200 } #=> {"a"=>100, "b"=>200}
h.clear #=> {}



String:

reverse: Returns a new string which is reversed.

"stressed".reverse #=> "desserts"

capitalize: Capitalize the first word.

a = "hello"
a.capitalize! #=> "Hello"
a #=> "Hello"
a.capitalize! #=> nil

 

tr: Returns a new string where the characters from the first argument are replaced with the characters in the second argument. Example: "abca".tr('ab', 'cd') -> "cdcc"

bytes: Returns the UTF/ASCII values (in base 10) of every character in the string, notice that one character can be composed of multiple bytes.

swapcase: Returns a new string with lowercase letters converted to uppercase & uppercase converted to lowercase.

"Hello".swapcase #=> "hELLO"
"cYbEr_PuNk11".swapcase #=> "CyBeR_pUnK11"

bytes_size: Returns the number of bytes that a string is composed of. Notice that this is different than the visible string lenght, because characters can be composed of multiple bytes.

include? Check if a string is part of another. Example: "cat".include?("at") # true

chars: Returns an array with the individual characters that form the string.

scan: Scans the string for a Regexp pattern & returns an Array with the results.

a = "cruel world"
a.scan(/\w+/) #=> ["cruel", "world"]
a.scan(/.../) #=> ["cru", "el ", "wor"]
a.scan(/(...)/) #=> [["cru"], ["el "], ["wor"]]
a.scan(/(..)(..)/) #=> [["cr", "ue"], ["l ", "wo"]]

chomp: Returns a new string with X removed from the end of the string. Where X is the newline character by default. An argument can be passed to override the default.

"hello".chomp #=> "hello"
"hello\n".chomp #=> "hello"
"hello\r\n".chomp #=> "hello"
"hello\n\r".chomp #=> "hello\n"
"hello\r".chomp #=> "hello"
"hello \n there".chomp #=> "hello \n there"
"hello".chomp("llo") #=> "he"
"hello\r\n\r\n".chomp('') #=> "hello"
"hello\r\n\r\r\n".chomp('') #=> "hello\r\n\r"

match: Scans the string for a Regexp pattern & returns a Match Data object with the results.

'hello'.match('(.)\1') #=> #<MatchData "ll" 1:"l">
'hello'.match('(.)\1')[0] #=> "ll"
'hello'.match(/(.)\1/)[0] #=> "ll"
'hello'.match(/(.)\1/, 3) #=> nil
'hello'.match('xx') #=> nil

chop: Returns a new string with the last character removed.

"string\r\n".chop #=> "string"
"string\n\r".chop #=> "string\n"
"string\n".chop #=> "string"
"string".chop #=> "strin"
"x".chop.chop #=> ""


strip: Returns a new string with leading and trailing whitespace removed.

" hello ".strip #=> "hello"
"\tgoodbye\r\n".strip #=> "goodbye"
"\x00\t\n\v\f\r ".strip #=> ""

clear: The string becomes an empty string.

a = [ "a", "b", "c", "d", "e" ]
a.clear #=> [ ]

 

unpack: This method takes a format string & uses that for decoding, returns an Array. This a pretty complex method that would require a mind-map of its own :)

"abc \0\0abc \0\0".unpack('A6Z6') #=> ["abc", "abc "]
"abc \0\0".unpack('a3a3') #=> ["abc", " \000\000"]
"abc \0abc \0".unpack('Z*Z*') #=> ["abc ", "abc "]
"aa".unpack('b8B8') #=> ["10000110", "01100001"]
"aaa".unpack('h2H2c') #=> ["16", "61", 97]
"\xfe\xff\xfe\xff".unpack('sS') #=> [-2, 65534]
"now=20is".unpack('M*') #=> ["now is"]
"whole".unpack('xax2aX2aX1aX2a') #=> ["h", "e", "l", "l", "o"]


delete: Returns a copy of the string with all characters in the intersection of its arguments deleted. This is another complex method, but here is an example: "hello".delete "lo" -> "he"

"hello".delete "l","lo" #=> "heo"
"hello".delete "lo" #=> "he"
"hello".delete "aeiou", "^e" #=> "hell"
"hello".delete "ej-m" #=> "ho"

liust/riust: Returns a new string that is padded by n spaces - the string size. The padding can be on the left (ljust) or on the right (rjust).

"hello".rjust(4) #=> "hello"
"hello".rjust(20) #=> " hello"
"hello".rjust(20, '1234') #=> "123412341234123hello"

"hello".ljust(4) #=> "hello"
"hello".ljust(20) #=> "hello "
"hello".ljust(20, '1234') #=> "hello123412341234123"

 

downcase: Returns a new string where all the character are downcased.

"hEllO".downcase #=> "hello"

gsub / gsub! Substitute all the occurences of a specific word or Regexp pattern. The regular version Returnss a new array, and the ! version modifies the original string.

"hello".gsub(/[aeiou]/, '*') #=> "h*ll*"
"hello".gsub(/([aeiou])/, '<\1>') #=> "h<e>ll<o>"
"hello".gsub(/./) {|s| s.ord.to_s + ' '} #=> "104 101 108 108 111 "
"hello".gsub(/(?<foo>[aeiou])/, '{\k<foo>}') #=> "h{e}ll{o}"
'hello'.gsub(/[eo]/, 'e' => 3, 'o' => '*') #=> "h3ll*"

upcase: Returns a new string where all the character are upcased.

"hEllO".upcase #=> "HELLO"

end_with? Returns true if the string ends with one of the suffixes given.

"hello".end_with?("ello") #=> true

# returns true if one of the +suffixes+ matches.

"hello".end_with?("heaven", "ello") #=> true

"hello".end_with?("heaven", "paradise") #=> false


each_byte: Similar to the 'bytes' method, but it lets you pass a block to do something with every byte.

"hello".each_byte {|c| print c, ' ' }
104 101 108 108 111

start_with? Returns true if the string starts with one of the suffixes given.

"hello".start_with?("hell") #=> true

# returns true if one of the prefixes matches.

"hello".start_with?("heaven", "hell") #=> true
"hello".start_with?("heaven", "paradise") #=> false


each_line: Breaks down the string into lines (using the newline character as reference). You can pass in a block to do something with each line.

"hello\nworld".each_line {|s| p s}
print "Example two\n"
"hello\nworld".each_line('l') {|s| p s}
print "Example three\n"
"hello\n\n\nworld".each_line('') {|s| p s}

Example one
"hello\n"
"world"
Example two
"hel"
"l"
"o\nworl"
"d"
Example three
"hello\n\n"

"world"


enconding: Returns a Encoding object that represents the current encoding for this string.

empty? Returns true if the string has a length of 0.

[].empty? #=> true

encode: Returns a new string with a new encoding. Can raise Encoding:Undefined Conversion Error & Encoding::InvalidByteSequenceError.


Split: Convert string to array.

a = "07:05:45"
a.split(":")
#=> ["07", "05", "45"]


Meta Programming:

send: Calls a method by name or symbol. Allows you to bypass the 'private' modifier.

class Klass
def hello(*args)
"Hello " + args.join(' ')
end
end

k = Klass.new
k.send :hello, "gentle", "readers" #=> "Hello gentle readers"

public_send: Same a send, but raises an exception if you try to call a private method.

1.public_send(:puts, "hello") # causes NoMethodError

method_missing: Invoked whenever a method is not defined on the current class. Arguments are: name, *args, &block.

class Roman
def roman_to_int(str)
# ...
end

def method_missing(methId)
str = methId.id2name
roman_to_int(str)
end
end


r = Roman.new
r.iv #=> 4
r.xxiii #=> 23
r.mm #=> 2000

 

eval/class_eval / instance_eval: Execute a string as Ruby code under the specified context (current object, other object or class). Warning: This one can be a source of security issues, so be careful what you feed to this method.

def get_binding(str)
return binding
end

str = "hello"
eval "str + ' Fred'" #=> "hello Fred"
eval "str + ' Fred'", get_binding("bye") #=> "bye Fred"

method: Given a method name it will return a Method object for that method if it exists. Example: [].method(:join)

instance_method: Given a method name it will return an Unbound Method object for that method if it exists. Example: Array.instance_method(join)

ancestors: Returns an Array of all the modules & parent classes of a class, in order.

instance_methods: Returns an array of all the instance methods, included those from parent classes. You can pass "false" as an argument to get only methods for the current class.

define_singelton_method: Defines a new singleton (class) method. The method name is a symbol passed as the first argument & the method body is the block passed to this method.

class A
class << self
def class_name
to_s
end
end
end

A.define_singleton_method(:who_am_i) do
"I am: #{class_name}"
end

A.who_am_i # ==> "I am: A"

guy = "Bob"
guy.define_singleton_method(:hello) { "#{self}: Hello there!" }
guy.hello #=> "Bob: Hello there!"

remove_method: Removes an instance method from this class. Use undef_method if you also want to remove this method from all the parent classes.

define_method: Defines a new instance method. The method name is a symbol passed as the first argument & the method body is the block passed to this method.

class A
  def fred
    puts "In Fred"
  end
  def create_method(name, &block)
    self.class.send(:define_method, name, &block)
  end
  define_method(:wilma) { puts "Charge it!" }
end
class B < A
  define_method(:barney, instance_method(:fred))
end
a = B.new
a.barney
a.wilma
a.create_method(:betty) { p self }
a.betty

In Fred
Charge it!

#<B:0x401b39e8>


included: Invoked whenever the receiver (the class defining this method) is included in another module or class.

extended: The equivalent of included, but for extended modules.

method_added: Invoked whenever an instance method is added to the receiver class.

method_removed: Invoked whenever an instance method is removed from the receiver (via

remove_method).

singleton_method_added: Invoked whenever a class method is added to the receiver class. 

module Chatty
def Chatty.singleton_method_added(id)
puts "Adding #{id.id2name}"
end

def self.one() end
def two() end
def Chatty.three() end
end


singleton_method_removed: Invoked whenever a singleton method is removed from the receiver.

const_get: Given a symbol or a string it looks for a constant with that name & returns its value. This will includes parent classes and modules.

module Foo
class Bar
VAL = 10
end

class Baz < Bar; end
end

Object.const_get 'Foo::Baz::VAL' # => 10
Object.const_get 'Foo::Baz::VAL', false # => NameError

const_set: Given a symbol & a value it looks for a constant with that name & updates its value.

Math.const_set("HIGH_SCHOOL_PI", 22.0/7.0) #=> 3.14285714285714
Math::HIGH_SCHOOL_PI - Math::PI #=> 0.00126448926734968
Object.const_set('foobar', 42) #=> NameError: wrong constant name foobar

alias_method: Makes a copy of the method. This can be used to retain access to methods that are overridden. Example: alias_method :new_method, :old_method

module Mod
alias_method :orig_exit, :exit

def exit(code=0)
puts "Exiting with code #{code}"
orig_exit(code)
end
end

include Mod
exit(99)

#=> Exiting with code 99


singleton_class: Returns the singleton class for any object.

class C
end

C.singleton_class? #=> false
C.singleton_class.singleton_class? #=> true

singleton_methods: Returns a list of all the singleton (class) methods defined on an object.

module Other
def three() end
end

class Single
def Single.four() end
end

a = Single.new
def a.one()
end

class << a
include Other
def two()
end
end

Single.singleton_methods #=> [:four]
a.singleton_methods(false) #=> [:two, :one]
a.singleton_methods #=> [:two, :one, :three]

instance_variable_set: Given a symbol or a string & a value it sets the value for that instance variable.

class Fred
def initialize(p1, p2)
@a, @b = p1, p2
end
end

fred = Fred.new('cat', 99)
fred.instance_variable_set(:@a, 'dog') #=> "dog"
fred.instance_variable_set(:@c, 'cat') #=> "cat"
fred.inspect #=> "#<Fred:0x401b3da8 @a=\"dog\", @b=99, @c=\"cat\">"

instance_variable_get: Given a symbol or a string it returns the value for that instance variable (nil if the variable is not set).

class Fred
def initialize(p1, p2)
@a, @b = p1, p2
end
end

fred = Fred.new('cat', 99)
fred.instance_variable_get(:@a) #=> "cat"
fred.instance_variable_get("@b") #=> 99


Other Ruby Concepts

require
require_relative
load
singleton methods/class
regular expressions
meta programming
lazy enumerations
Ruby object hierarchy
conditionals(if, else, elsif, unless, case)
while loops
using and defining methods
instance method
class method
instance variable
class variable
default arguments
variable arguments
enumerable
accessors
ranges
hash
struct
modules
expects
inheritance & composition
Introspection
Reflection
serialization(JSON/YAML/CSV)


Thanks for reading the article. Hope this article will help you to know most of the basic concept of Ruby. If you want to learn more you can buy this book.

Comments

Popular Posts

Install and configure Network simulator (ns3) on Ubuntu 14.04