Intro to Ruby
For Sysads
Why Ruby?
- We are already using it in puppet
- It makes easy to reason about logic compared to bash
- Its fun.
- Its fast.
- Lots of online documentation.
- 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,093