Intro to Ruby



For Sysads

Why Ruby?


  1. We are already using it in puppet
  2. It makes easy to reason about logic compared to bash
  3. Its fun.
  4. Its fast.
  5. Lots of online documentation.
  6. Functional Programming

Lets Quick Start With Values

#values

"string"     #this is string, strings can be double or single quoted
1            #this is number
4.0          # this is float
true         #this is boolean
false        #the other boolean
nil          #another value, like boolean but not same
/regex/      #regexs are builtin and readily available
[1,2,3]      # arrays

#hash can have anything as key and value
{:a => "a", :b => "b", "c" => c }

More Values

#common expressions
true == false                  #=> false
false !=  true                 #=> true
"somestring" =~ /string$/      #=> true (as it matches)not 
not true                       #=> false
false or true                  #=> true
true and false                 #=> false

require "time"                 #this is how we import a library
puts "string"                  #print string
now = Time.now()               #assign value
puts "current time is #{time}" #string interpolation

Loops,Iteration

3.times do
  puts "something"
end

for i in 0..9 do
    puts "#{i}"
end

i = 0 ; while i < 10 do
    i = i + 1; puts i
end

i = 0; until i > 10 do 
    i = i + 1; puts i
end

Loops,Iteration

array = ["this","is","an","array"]

# ugly way
for i in 0..array.length do
puts array[i]
end

# better way
array.each do |v|
puts v
end

hash = {:a => "a" , :b => "b"}
hash.each do |k,v|
puts k,v
end

Loops,Iteration

# infinite loop, use with caution
loop do
print "Input: "
line = gets
break if !line or line =~ /^qQ/
end # generate valued loop, something like for (0..10).each do |v| next if v < 5 puts v end

Flow Control

x = 1

if x == 2
  puts "x is 2"
elsif x == 1
  puts "x is 1"
else 
  puts "x is neither one 1 or 2"
end

y = 6 if x == 1               # we can use if in assignment statement

Flow Control

unless false                  # unless is short for if not
puts "this will run"
end

y = 7 unless defined? (y) #we can use unless in assignment statement # assign using if else block y = if someexpression() somefunction() else someotherfunction() end

Flow Control

test = somefunc()

case test
    when test.is_a? String
        puts "test is string"
    when test.is_a? FixNum
        puts "test is a integer"
    when test.is_a? Float
        puts "test is a floating point number"
    else
        puts "can't identify what test is"
end

Functions

def func(arg1,arg2)
    arg1 + arg2      #last statement's value is returned
end

puts "val"                # print statement returns nil

def func2(arg1 ,arg 2,arg 3)
  puts arg1.call(arg2,arg3)    # prints value but returns nil as puts ...
end                            # returns nil

func2(func,1,2)  #prints sum of arg2 and arg3, functions are first class


Ruby Fundamentals

Almost Everything in ruby is an object, lets examine using reflection api

3.class              #objects are instance of a class
3.methods            #objects have methods
3.class.class        #classes inherits Class class

3.class.ancestors    #classes have ancestors
3.is_a? Object       #objects are instance of object class
3.is_a? Class        #But instances of a class are not class

Class.is_a? Object   #class Class inherits Object class

3.send("abs")        #You can send methods to objects by creating strings 



Ruby Fundamentals..

Declaring class

class Someclass
  @@var1 = 0         #a class variable shared across different instances of class
  def initialize(v1) #initialize instance variable, different for each instance
    @v1 = v1
  end
  def instancemethod(v2)    #instance method
    puts @v1 + v2       #v2 is a local variable for functino
  end
  def self.classmethod(v3)
    @@var1 += v3
  end
end
v = Someclass.new 1 ; v.instancemethod(5)
Someclass.classmethod(6)

Ruby Fundamentals

Extend existing class

 class Hash
def inverse
self.reduce({}){ |h,(k,v)| (h[v] ||=[]) << k; h}
end
end k = {"a" => 1, "b" => 2, "c" => 1} k.inverse #=> {1 => ["a","c"],2 => "b"}

Calling external code

k = `ls -alh /home/`      # gives standard output as string
y = %x[ls -alh /home]     # does the same thing as above

$?.exitstatus             # will give exitcode of the last command ran
$?.pid                    #gives process id of last command ran


val = "/home/"

dirs = `ls #{val}`


dirs.split("\n").grep(/somefile/) 


Functional Programming

  • Makes program easy to reason about
  • Takes a little getting used to
  • Fast, concise logic
  • Higher order functions
  • Very useful when using ruby collections

Functional programming..

#Higher order function examples

$dates = (0..3).to_a.map{ |n| Time.now - 86400 * n }.map {|n| n.strftime "%d-%m-%Y"}

$hosts = Dir.entries("/data/hosts/").select {|v| v =~ /.net|.in/}

$hosts = Dir.entries("/data/hosts/").select {|v| v =~ /.net|.in/}.reject { |v| v =~ /bll-2/}

Useful Libraries

require 'time'      #for time related functions
require 'fileutils' #for file related functons

require 'optparse'  #to create cli parser 

require 'resolv'    #for dns related functions


require 'json'      #for json related functions
require 'yaml'      #for reading yaml files
require 'rexml'     #for xml parsing


require 'pp'        #for pretty printing, useful for debugging



Helpful tips

  • Use ri for offline help
  • Use rvm/rbenv for switching ruby version
  • irb is your friend, helps to quickly test
  • pry is another useful shell to
  • ruby-doc.org is helpful
  • Don't forget stack overflow
  • Google usually points in the right direction

Useful links

  • http://zetcode.com/lang/rubytutorial/flowcontrol/
  • http://tech.natemurray.com/2007/03/ruby-shell-commands.html
  • http://stackoverflow.com/questions/4967556/ruby-craziness-class-vs-object
  • http://ruby-doc.org/

Intro to Ruby

By Ayush Goyal

Intro to Ruby

  • 1,032