ruby tutorial with code samples
DESCRIPTION
ruby programmingTRANSCRIPT
12/14/2015 Ruby Tutorial with Code Samples
http://www.fincher.org/tips/Languages/Ruby/ 1/31
Ruby for the Attention Deficit Disorder Programmer let's start learningRuby fast!
"Java is a pair of scissors, Ruby is a chainsaw."
1. Install RubyFor windows you can download Ruby from
http://rubyforge.org/frs/?group_id=167 for Linux tryhttp://www.rpmfind.net.
2. Our first programEnter the following into the file, "test.rb".
puts "Howdy!"
At the C: prompt enter,
C:>ruby test.rb
This produces:
Howdy!
OK, daylight's burning, let's move on.
3. Output in Ruby
"puts" writes to the screen with a carriage return at the end. "print" does the same thing without the carriage return. "printf" formats variables like in C and Java 5.
puts "puts works" puts " with line breaks."
print "print works" print " with no line breaks."
printf("\n\nprintf formats numbers like %7.2f, and strings like %s.",3.14156,"me")
This produces:
puts works with line breaks.
print works with no line breaks.
12/14/2015 Ruby Tutorial with Code Samples
http://www.fincher.org/tips/Languages/Ruby/ 2/31
print works with no line breaks. printf formats numbers like 3.14, and strings like me.
4. Reading from the ConsoleUse "gets"
puts "What is your name?" $name = STDIN.gets puts "Hi "+$name
5. FunctionsA. Our first Ruby function
'def' starts the definition of a method, and 'end' ends it nocute little curly braces.
def welcome(name) puts "howdy #name" # inside double quotes, # will evaluate the variableend welcome("nana") # traditional parens
This Produces:
howdy nana
B. Parentheses are optional
def welcome(name) puts "howdy #name" # inside double quotes, # will evaluate the variableend welcome "visitor" #look, ma, no parentheses
This Produces:
howdy visitor
The same is true of methods without arguments
"hello".upcase() => "HELLO" "hello".upcase => "HELLO"
C. How to return values from a functionWe can use the faithful 'return'
12/14/2015 Ruby Tutorial with Code Samples
http://www.fincher.org/tips/Languages/Ruby/ 3/31
def multiply(a,b) product = a * b return product end puts multiply(2,3) =>6
Oddly enough you can leave out the "return" statement, andRuby will helpfully return the last expression:
def mult(a,b) product = a * b end puts mult(2,3)
or even simpler, leave out "product" and ruby returns thecontents of the last expression:
def mult(a,b) a * b end puts mult(3,3) =>9
D. Optional argument valuesRuby lets you assign values to arguments which may, or may
not be supplied as shown below:
def test(a=1,b=2,c=a+b) puts "#a,#b,#c" end test => 1,2,3 test 5 => 5,2,7 test 4, 6 => 4,6,10 test 3, 4, 6 => 3,4,6
E. Extra argumentsExtra arguments are gathered into the last variable if
preceded with a "*". ("each" is an iterator that loops over itsmembers).
def test(a=1,b=2,*c) puts "#a,#b" c.each|x| print " #x, " # We will learn about "each" very soon. I promise.end test 3, 6, 9, 12, 15, 18
This produces:
3,6 9, 12, 15, 18,
12/14/2015 Ruby Tutorial with Code Samples
http://www.fincher.org/tips/Languages/Ruby/ 4/31
F. Multiple return values
def getCostAndMpg cost = 30000 # some fancy db calls go here mpg = 30 return cost,mpg end AltimaCost, AltimaMpg = getCostAndMpg puts "AltimaCost = #AltimaCost, AltimaMpg = #AltimaMpg"
Produces:
AltimaCost = 30000, AltimaMpg = 30
6. Open ClassesYou can add methods to existing library classes. For example, in
C# 2.0, Microsoft added the very helpful string function,IsNullOrEmpty() which replaces the unwieldly construct: if(mystring != null && mystring != "") In Ruby you don't have to wait for the mavens in Redmond to decideyou need a new string function, you can add it yourself.
class String def NullOrEmpty? (self == nil || self == "") end end puts "test".NullOrEmpty? puts "".NullOrEmpty?
Is this way cool? Yes. Is this very dangerous? Yes. Remember,Ruby is a chainsaw.
7. Variable namingOk, let's slow down and learn some basics about variable names
A. Global variables start with '$'B. Class variables start with '@@'C. Instance variables start with '@'D. Local variables, method names, and method parameters start
with a lower case letterE. Class names, module names and constants start with an
uppercase letterF. Variables names are composed of letters, numbers and
underscoresG. Method names may end with "?", "!", or "=". Methods ending
with a "?" imply a boolean operation (eg, "instance_of?").Methods ending with "!" imply something dangerous, likestrings being modified in place (eg, "upcase!")
8. Interesting tidbits about Ruby,
12/14/2015 Ruby Tutorial with Code Samples
http://www.fincher.org/tips/Languages/Ruby/ 5/31
A. '#' is the line comment character, all characters after this areignored. Confusingly '#' can appear within quotes with adifferent meaning.
B. No semicolons are needed to end lines, but may be used toseparate statements on the same line
C. A backslash (\) at the end of a line is used for continuationD. Indenting is not significant, unlike pythonE. Types of variables do not need to be declaredF. Lines between =begin and =end are ignoredG. Lines following "__END__" on its own line with no white
space, are ignoredH. A tiny demonstration of these:
# sample program showing special characters like comments # I'm a comment line a = 1 #notice no semicolon and no type declarationb = 2; c = 3 #notice two statements on one line name = "Abraham \ Lincoln" # a line continued by trailing \ puts "#name" =begin I'm ignored. So am I. =end puts "goodbye" __END__ 1 2 3 4
Abraham Lincoln goodbye
9. Variable TypesIn Ruby, variables don't have a specific type associated with them.
All variables are objects, so we only play with pointers to thoseobjects, and those pointers are type agnostic.
bat = "Louisville slugger" bat = 1.23
11. QuotesLike in Perl, single quotes and double quotes have different
meanings.Double quotes means "please interpret special characters in this
string". Things like backslash n ('\n') are converted to their typicalvalues. The #name construct is converted to its value.
With single quotes, no special characters are interpreted.Examples:
12/14/2015 Ruby Tutorial with Code Samples
http://www.fincher.org/tips/Languages/Ruby/ 6/31
name="Mike" puts "hi #name" =>hi Mike puts "hi\n #name" => hi (carriage return)Mike puts 'hi\n #name' => hi\n #name (no substitutions are made since using single quote)
The braces are optional for global and instance variables
$myname="Ishmael" puts "hi #$myname" =>hi Ishmael
12. ObjectsA great thing about Ruby is that numbers and strings are real
objects.
1.5.floor() => "1"
This lets us do some cool things. Instead of
if( x > 7 && x < 12 ) ...
We can write
if x.between?(7,12) do ...
13. Big NumbersRuby automatically increases the precision of variables
for i in 1..1000 puts "2 ** #i = #2**i" end
Produces:
2 ** 1 = 2 2 ** 2 = 4 2 ** 3 = 8 2 ** 4 = 16 2 ** 5 = 32 2 ** 6 = 64 2 ** 7 = 128 2 ** 8 = 256 2 ** 9 = 512 2 ** 10 = 1024 ... 2 ** 1000 = 10715086071862673209484250490600018105614048117055336074437503883703510511249361224931983788156958581275946729175531468251871452856923140435984577574698574803934567774824230985421074605062371141877954182153046474983581941267398767559165543946077062914571196477686542167660429831652624386837205668069376
12/14/2015 Ruby Tutorial with Code Samples
http://www.fincher.org/tips/Languages/Ruby/ 7/31
Ruby will increase the precision of the number, or decrease it asneeded:
x = 1000000 puts "#x "+x.class.to_s => 1000000 Fixnum x = x * x puts "#x "+x.class.to_s => 1000000000000 Bignum x = x / 1000000 puts "#x "+x.class.to_s => 1000000 Fixnum
14. Parallel AssignmentYou can swap the values in variables without the use of a temp
variable. Remember your first programming class: Swap the values in"i" and "j"? You had to use a "t" variable to store one of the valuesfirst. Not needed in Ruby.
i = 0 j = 1 puts "i = #i, j=#j" i,j = j,i puts "i = #i, j=#j"
Produces:
i = 0, j=1 i = 1, j=0
15. CollectionsA. Arrays
a. An array of known objects can be created by enclosing themin square brackets.
nums = [1, 2.0, "three"] puts nums[2] => three
Ruby arrays, like all rightthinking collections, are zerobased.
b. You can use negative indexes to start from the end of thearray
nums = [1, 2.0, "three", "four"] puts nums[1] => four
Using "1" is so much more concise than"nums[nums.length()1]".
c. You can even use the handy "first" and "last" methods.
12/14/2015 Ruby Tutorial with Code Samples
http://www.fincher.org/tips/Languages/Ruby/ 8/31
[1,2,3].last => 3 [1,2,3].first => 1
d. lengthTo get the count, or size, of an array, use the "length"
method.
mystuff = ["tivo","nokia", "ipaq"] # make a string array puts mystuff.length => 3
e. %w shortcutSince many arrays are composed of single words and all
those commas and quote marks are troublesome, Rubyprovides a handy shortcut, %w:
mystuff = %wtivo nokia ipaq # make a string array
f. inspectTo look at contents of an object use the "inspect" method.
Even more convenient is to use "p" as a shorthand for "putsobj.inspect"
myarray = [1,2,5,7,11] puts myarray puts myarray.inspect p myarray
Produces:
1 2 5 7 11 [1, 2, 5, 7, 11] [1, 2, 5, 7, 11]
g. Arrays can act like queues and sets
# & is the intersection operator puts [1,2,3] & [3,4,5] # prints 3
# + is the addition operator puts [1,2,3]+ [3,4,5] # prints 1,2,3,3,4,5
# removes items from the first array that appear in the second puts [1,2,3] [3,4,5] # prints 1,2
# pop returns the last element and removes it from the array alpha = ["a","b","c","d","e","f"] puts "pop="+alpha.pop # pop=f
12/14/2015 Ruby Tutorial with Code Samples
http://www.fincher.org/tips/Languages/Ruby/ 9/31
puts alpha.inspect # ["a", "b", "c", "d", "e"]
# push appends elements to the end of an array alpha = ["a","b","c"] alpha.push("x","y","z")puts alpha.inspect # ["a", "b", "c", "x", "y", "z"]
# shift returns the first element and removes it from the array alpha = ["a","b","c","d","e","f"] puts "shift="+alpha.shift # shift=a puts alpha.inspect # ["b", "c", "d", "e", "f"]
# unshift appends elements to the beginning of an array alpha = ["a","b","c"] alpha.unshift("x","y","z") puts alpha.inspect # ["x", "y", "z", "a", "b", "c"]
B. HashesThis type of collection is also called a dictionary or an
associative array.a. Simple hash of cars and their makers
cars = 'altima' => 'nissan', 'camry' => 'toyota', 'rx7' => 'mazda' puts cars['rx7'] => mazda
b. You can create a hash and fill it dynamically
dict = # create a new dictionary dict['H'] = 'Hydrogen' #associate the key 'H' to the value 'Hydrogen'dict['He'] = 'Helium' dict['Li'] = 'Lithium' p dict['H'] # prints "Hydrogen" p dict.length # prints 3 p dict.values # prints ["Lithium", "Helium", "Hydrogen"] p dict.keys # prints ["Li", "He", "H"] p dict # prints "Li"=>"Lithium", "He"=>"Helium", "H"=>"Hydrogen"
c. Hash[]You can also create Hashes with square brackets by
prefixing with "Hash":
toppings = Hash["pancakes","syrup","Pizza","Pepper","Cereal"puts toppings.inspect
Produces:
"Pizza"=>"Pepper", "Cereal"=>"Sugar", "pancakes"=>"syrup"
12/14/2015 Ruby Tutorial with Code Samples
http://www.fincher.org/tips/Languages/Ruby/ 10/31
d. eachThe "each" method is a wonderful way to iterate over the
keys
toppings = Hash["pancakes","syrup","Pizza","Pepper","Cereal"toppings.each|key, value| puts "#key points to #value"
Produces:
Pizza points to PepperCereal points to Sugarpancakes points to syrup
e. selectThe "select" method populates a new array with
members which meet a criteria
salaries = Hash["bob",10.9,"larry",7.5,"jimmy",6.0,"jerry",6.5salaries.inspect mySalaryArray = salaries.select|name,salary| salary > 7.0puts mySalaryArray.inspect #prints [["larry", 7.5], ["bob", 10.9]]
C. RangesRanges are composed of expr..expr or expr...expr. Two dots
includes the last element, three dots excludes it.
('a'..'g').each |letter| puts letter
Produces:
a b c d e f g
(1...3).each |num| puts num
Produces only two numbers since "..." does not include thelast element.:
1 2
12/14/2015 Ruby Tutorial with Code Samples
http://www.fincher.org/tips/Languages/Ruby/ 11/31
16. Control StatementsA. if In an "if" statement anything but the two special values,
"false" and "nil" are considered true. Even zero is true for allyou C/C++ programmers.
income = 30000.00 if income < 10000 rate = 0.02 elsif income < 30000 rate = 0.28 else rate = 0.5 end puts rate
B. case
grade = 10 school = case grade when 0..5 "elementary" when 6..8 "middle school" when 9..12 "high school" else "college" end puts "grade #grade is in #school"
C. for
for i in 1..4 puts "hi #i" end
The ranges can of course have variables
top = 6 for i in 1..top puts "hi #i" end
D. exit
lines = IO.readlines("data.txt") if lines.length < 100 exit 2 end puts lines.length
12/14/2015 Ruby Tutorial with Code Samples
http://www.fincher.org/tips/Languages/Ruby/ 12/31
E. loopiterates over code until a "break" or eternity ends
i=0 loop do break if i > 5 puts i i += 1 end
17. Statement modifiersThese are just syntatic sugar.
A. ifThe "if" clause may be placed at the end of a statement
balance = 10.0 puts "Bankrupt" if balance < 0.0
B. unless"unless" is placed at the end of a statement
balance = 10.0 puts "Bankrupt" unless balance > 0.0
C. while"while" may be after its block
f=2 puts f=f+2 while f < 10 =>4 =>6 =>8 =>10
18. IteratorsA. while
i = 0 while i < 5 i = i+1 puts i end
B. "times"
n = 10 n.times |i| print i
12/14/2015 Ruby Tutorial with Code Samples
http://www.fincher.org/tips/Languages/Ruby/ 13/31
Produces:
0123456789
C. "each"
animals = %w(lions tigers bears) animals.each|kind| print kind
lionstigersbears
D. "each" with ranges
('m'..'z').each |ch| print ch
mnopqrstuvwxyz
E. "upto"
n=0 ; max=7 n.upto(max) |num| print num
01234567
19. You gotta have class.A. Classes
Class definitions start with "class" and end with "end".Remember that class names start with a capital letter. Notice thesyntax is "object.new" for creating an object and that the"initialize" method contains code normally found in theconstructor. Here's a small example:
class Person def initialize(fname, lname) @fname = fname @lname = lname end end person = Person.new("Augustus","Bondi") print person
Produces:
#<Person:0x257c020>
12/14/2015 Ruby Tutorial with Code Samples
http://www.fincher.org/tips/Languages/Ruby/ 14/31
which is true, but not helpful.
B. The "ToString" method, to_s
class Person def initialize(fname, lname) @fname = fname @lname = lname end def to_s "Person: #@fname #@lname" end end person = Person.new("Augustus","Bondi") print person
Produces:
Person: Augustus Bondi
C. SubclassingIn Ruby subclassing is done with the "<" character
class Employee < Person def initialize(fname, lname, position) super(fname,lname) @position = position end def to_s super + ", #@position" end end employee = Employee.new("Augustus","Bondi","CFO") print employee
Produces:
Person: Augustus Bondi, CFO
if we try to print the first name directly like
print employee.fname
we get the error message,
CFOtest.rb:21: undefined method 'fname'
But why is that? We've printed variables a zillion times up tilnow and it's always worked. What changed? Up until now we'vecreated variables in a program without classes (actually all arevariables were members of a default object that were accessable
12/14/2015 Ruby Tutorial with Code Samples
http://www.fincher.org/tips/Languages/Ruby/ 15/31
inside itself). Now we are using real classes and that brings upthe point of visibility of members outside the class. We now haveto specify if a variable is open to the outside, like "public","private", "protected", "internal" in other languages.
To grant access to read a variable we declare it after"attr_reader". attribute with the following:
attr_reader :fname, :lname
then
print employee.fname => "Augustus"
To allow writing to a variable use "attr_writer",
class Employee < Person def initialize(fname, lname, position) super(fname,lname) @position = position end def to_s super + ", #@position" end attr_writer :position end employee = Employee.new("Augustus","Bondi","CFO") puts employee puts employee.fnameemployee.position = "CEO" puts employee
D. Virtual Attributes
class Employee < Person def initialize(fname, lname, position) super(fname,lname) @position = position end def to_s super + ", #@position" end attr_writer :position def etype if @position == "CEO" || @position == "CFO" "executive" else "staff" end end end employee = Employee.new("Augustus","Bondi","CFO") employee.position = "CEO" puts employee.etype => executive employee.position = "Engineer"
12/14/2015 Ruby Tutorial with Code Samples
http://www.fincher.org/tips/Languages/Ruby/ 16/31
puts employee.etype => staff
20. Regular ExpressionsStrings can be compared to a regular expression with "=~".
Regular expressions are surrounded by "//" or "%r". Anything but thetwo special values, "false" and "nil" are considered true.Expression Result Description
/a/ =~ "All Gaul is dividedinto three parts" 5 finds the first "a" at position
5
%ra =~ "All Gaul is dividedinto three parts" 5 same thing with alternate
syntax
/ree/ =~ "All Gaul is dividedinto three parts" 27 finds "ree" at position 27
/^a/ =~ "All Gaul is dividedinto three parts" nil "^" implies at the beginning
of a line. nil is false.
/^A/ =~ "All Gaul is dividedinto three parts" 0 casesensitive, remember
that "0" is true
/s$/ =~ "All Gaul is dividedinto three parts" 35 "$" implies at the end of a
line
/p.r/ =~ "All Gaul is dividedinto three parts" 31 "." matches any character
21. BlocksAnd now to one of the coolest things about Ruby blocks. Blocks
are nameless chunks of code that may be passed as an argument toa function.
A. Simple Example
def whereisit yield yield yield end whereisit puts "where is the money?"
Produces:
where is the money? where is the money? where is the money?
In the above example 'puts "where is the money?"' is calleda block. That chunk of code is passed to the method "whereisit"and executed each time the "yield" statement is executed. Youcan think of the "yield" being replaced by the block of code.
B. Blocks can take argumentsHere the method "cubes" takes the max value.
12/14/2015 Ruby Tutorial with Code Samples
http://www.fincher.org/tips/Languages/Ruby/ 17/31
def cubes(max) i=1 while i < max yield i**3 i += 1 end end cubes(8) |x| print x, ", " => 1, 8, 27, 64, 125, 216, 343, sum = 0 cubes(8) |y| sum += y print "\nsum=",sum => sum=784 product = 1 cubes(8) |z| product *= z print "\nproduct=",product => product=128024064000
Think of the "yield i**3" in the function cubes as beingreplaced with the block, '|x| print x, ", "'. The value following the"yield" is passed as the value "x" to the block.
C. Multiple arguments may be passed to blocks.
def employee(empId) #next 2 lines simulated from calling a database on the empId lastname = "Croton" firstname = "Milo" yield lastname,firstname #multiple arguments sent to blockend employee(4) |last,first| print "employee ",": ",first, " ",last
Produces:
employee : Milo Croton
D. Local variables can be shared with a blockEven though rate is a local variable, it is used inside the
block.
def tip(mealCost) yield mealCost end rate = 0.15 mytip = tip(10.0) |cost| cost * rate print "tip should be: ",mytip
Produces:
tip should be: 1.5
E. Blocks are built in to many objects in rubya. each
12/14/2015 Ruby Tutorial with Code Samples
http://www.fincher.org/tips/Languages/Ruby/ 18/31
iterates through each item of a collection
[1,2,3,4].each|x| print x**2," "
Produces:
1 4 9 16
b. detectreturns the first item matching a logical expression
numbers = [1,3,5,8,10,14] firstDoubleDigit = numbers.detect |x| x > 9 print firstDoubleDigit => 10
c. selectreturns all items matching a logical expression
numbers = [1,2,3,4,5,6,7]; evens = numbers.select|x| x % 2 == 0 p evens => [2, 4, 6]
d. collectreturns an array created by doing the operation on each
element.
[1,2,3,4].collect|x| x**3 => [1, 8, 27, 64] ["the","quick","brown", "lox"].collect|x| x.upcase => ["THE"
e. inject"inject" is the "fold" or "reducer" function in Ruby. "inject"
loops over an enumerable and performs an operation oneach object and returns a single value.
primes = [1,3,5,7,11,13]; #using "inject" to sum. We pass in "0" as the initial value sum = primes.inject(0)|cummulative,prime| cummulative+primeputs sum =>40 #we pass in no initial value, so inject uses the first element product = primes.inject|cummulative,prime| cummulative*primeputs product =>15015 #just for fun let's sum all the numbers from 1 to, oh, say a million sum = (1..1000000).inject(0)|cummulative,n| cummulative+nputs sum =>500000500000 #you can do interesting things like build hashes hash = primes.inject() |s,e| s.merge( e.to_s => e ) p hash # => "11"=>11, "7"=>7, "13"=>13, "1"=>1, "3"=>3, "5"=>5
12/14/2015 Ruby Tutorial with Code Samples
http://www.fincher.org/tips/Languages/Ruby/ 19/31
22. File I/OA. Read an entire file into a string
file = File.new( "t1.php" ) mytext = file.read
B. Read an entire file into an array of lines
lines = IO.readlines("data.txt") puts lines[0] #prints the first line
C. Read a file line by line
file = File.open("res.txt") while line = file.gets puts line end
Or you can use the IO class
IO.foreach("data.txt") |line| puts line
D. Read a file line by lineYou should ensure the file is closed as well.
begin file = File.open("res.txt") while line = file.gets puts line end ensure file.close end
E. Read only a few bytes at a timeThe following snippet of code reads a file which may have no
line breaks and chops it into 80 character lines
require 'readbytes' file = File.new( "C:/installs/myapp_log.xml" ) while bytes = file.readbytes(80) print bytes+"\r\n" end file.close
F. Reads a large XML file and inserts line breaksUses TruncatedDataError to grab the last few slacker bytes
from the end.
12/14/2015 Ruby Tutorial with Code Samples
http://www.fincher.org/tips/Languages/Ruby/ 20/31
# reads an xml file without line breaks and puts a line break before each '<'require 'readbytes' file = File.new( "C:/installs/SurveyDirector_log.xml" ) begin while bytes = file.readbytes(80) print bytes.gsub(/</,"\r\n<") end rescue TruncatedDataError #the last read had less chars than specified #print the rest of the data. $! is the exception. # ".data" has the extra bytes print $!.data.gsub(/</,"\r\n<") ensure file.close unless file.nil? end
23. method_missing a wonderful ideaIn most languages when a method cannot be found and error is
thrown and your program stops. In ruby you can actually catch thoseerrors and perhaps do something intelligent with the situation. A trivialexample:
class MathWiz def add(a,b) return a+b end def method_missing(name, *args) puts "I don't know the method #name" end end mathwiz = MathWiz.new puts mathwiz.add(1,4) puts mathwiz.subtract(4,2)
Produces:
5 I don't know the method subtract nil
24. While the ruby program is loading, you can execute code inside aspecial block labeled "BEGIN" pretty nifty. After the interpretor hasloaded the code, but before execution, you can execute code in the"END" block.
puts "main program running" END puts "program ending" BEGIN puts "I'm loading"
12/14/2015 Ruby Tutorial with Code Samples
http://www.fincher.org/tips/Languages/Ruby/ 21/31
Produces:
I'm loading main program running program ending
25. converting between strings and intsUse the to_i and to_s methods
"3".to_i #return an integer 3.to_s # returns a string
26. Using XML Dom ParserREXML goes standard with Ruby 1.8. Sample to print all "div"
elements whose "class" attribute is set to "entry".
require "rexml/document" file = File.new( "t0.xml" ) doc = REXML::Document.new file doc.elements.each("//div[@class='entry']") |element| puts element
27. Run a few lines directly from the command line with the "e"option
c:\home\mfincher>ruby e 'sleep 2' c:\home\mfincher>ruby e 'puts 3*4' 12 c:\home\mfincher>ruby e 'puts 3*4; puts 4*4' 12 16
28. Editing files in placeRuby offers a simple way to make a string substitution in many
files all at once with a single line of code. The "p" option loops overthe files, the "i" is the backup extension. With this command we arechanging all the documentation from version 1.5 to 1.6, but theoriginal files are renamed to ".bak".
C:\home\mfincher\ruby>more v2.txt Regarding version 1.5 ... .... version 1.5 is easy to install
C:\home\mfincher\ruby>ruby pi.bak e "gsub(/1.5/,'1.6')" v*.txt
C:\home\mfincher\ruby>more v2.txt Regarding version 1.6 ... .... version 1.6 is easy to install
12/14/2015 Ruby Tutorial with Code Samples
http://www.fincher.org/tips/Languages/Ruby/ 22/31
C:\home\mfincher\ruby>more v2.txt.bak Regarding version 1.5 ... .... version 1.5 is easy to install
29. Example of printing duplicate lines in sorted file.
#prints duplicate lines in sorted files in the file passed in as first arg file = File.open(ARGV[0]) lastLine = "" counter = 0 while line = file.gets counter += 1 if lastLine == line puts "#counter-1: #line#counter: #line\r\n" end lastLine = line end puts "done. Processed #counter lines"
30. Ruby has its own interpreted shell, irb.
C:\home\mfincher>irb irb(main):001:0> puts "Hello World" Hello World=> nil irb(main):002:0> a=1 => 1 irb(main):003:0> a*2 => 2 irb(main):004:0>
31. ruby can take input from stdin
echo 'puts "hello"' | ruby
32. to pass a string on the url it needs to be "escape"'d first.
require 'uri' ... URI.escape("some string...")
33. Example to remove "funny" characters from a filenameExample of iterating over the filenames in a directory, using
regular expression substitution in strings, and renaming files.
#replaces any "funny" characters in a filename in the current directory with an underscore#if the new file name already exists, this skips it.
12/14/2015 Ruby Tutorial with Code Samples
http://www.fincher.org/tips/Languages/Ruby/ 23/31
Dir.foreach(".") |f| print "testing \"#f\"" if f =~ /[^\w\-\.]/ #filename contains something other than letters, numbers, _,, or . puts "\r\n name with funny characters: #f" newName = f.gsub(/[^\w\.\-]/,"_") # \w is any word character, letter,num or _ if File.exist?(newName) puts " File #newName already exists. Not renaming." else puts " renaming #f to #newName" File.rename(f,newName) end else puts " it's ok." end
34. Looping over list of arguments
ARGV.each |f| puts f counter = 0 file = File.open(f,"r") ftmp = f+".tmp" tmp = File.open(ftmp,"w") while line = file.gets if line =~ /pid="2"/ counter += 1 line = line.gsub(/pid="2"/,"pid=\"#f:#counter\"") puts line end tmp.print line end file.close tmp.close puts "renaming #ftmp to #f" File.rename(ftmp,f)
35. Miscellanous Commandscommand description example result
global_variables returns all global variables
local_variables returns all local variables
sleep seconds sleeps specified seconds
rand returns a random numberbetween 0 and 1
rand(max) returns int between 0 and max
warn like print, but writes to STDERR
Interesting string functionscommand description example result
12/14/2015 Ruby Tutorial with Code Samples
http://www.fincher.org/tips/Languages/Ruby/ 24/31
center centers string "City".center(20) "________City________"
ljust left justifies "State".ljust(30) "State_________________________"
rjust right justifies "State".rjust(30) "_________________________State"
include?does the stringinclude thissubstring
"this is a test".include?('is') true
gsub global regexreplacesments
"this is atest".gsub(/[aeiou]/,'_\1') th_s _s _ t_st
tr translates "The greatest of theseis".tr('aeiou','*') Th* gr**t*st *f th*s* *s
each splits anditerates
"one:two:three".each(':')|x| puts x
one: two: three
36. DateTime
puts DateTime.now #prints 20061125T14:26:150600 puts Date.today #prints 20061125 puts Time.now #prints Sat Nov 25 14:29:57 Central Standard Time 2006
37. Using 'require'require will let your access code from other files. 'require' looks in
directories specified in $LOAD_PATH to find the files. Theenvironmental variable RUBYLIB can be used to load paths into$LOAD_PATH.
C:\home\mfincher\ruby>irb irb(main):001:0> p $LOAD_PATH ["c:/opt/ruby/lib/ruby/site_ruby/1.8", "c:/opt/ruby/lib/ruby/site_ruby/1.8/i386-msvcrt" "c:/opt/ruby/lib/ruby/1.8/i386-mswin32", "."] => nil
You can put a library like 'startClicker.rb' in any of those directoriesand ruby will find it.
require 'startClicker'
38. BuiltIn Command InterpreterWith the "eval" method you can create your own interpreter
language and run it during execution.
irb(main):007:0> a = 6 => 6 irb(main):008:0> b = 7 => 7 irb(main):009:0> eval "c=a+b"
12/14/2015 Ruby Tutorial with Code Samples
http://www.fincher.org/tips/Languages/Ruby/ 25/31
=> 13 irb(main):010:0> puts c 13
39. Introspection with ObjectSpaceYou can find all the objects in your program of a particular type
using ObjectSpace.each_object.
class Person def initialize(name,age) @name = name @age = age end attr_reader :nameend p = Person.new("Alfred",34) p2 = Person.new("Janie",31) ObjectSpace.each_object(Person) |s| puts s.name
Produces:
Janie Alfred
40. TestingRuby comes right out of the box with a testing framework. Here's a
quick example:
require 'test/unit'
class TestMe < Test::Unit::TestCase
def test_add s = 1 + 1 assert_equal(2, s) end
end
41. Read a URL and print the web page to the screen.This will get a particular page and print to the screen:
require 'open-uri' open('http://www.fincher.org/Misc/Pennies') |f| print f.read
This will read a file of urls and print all to the screen:
#Reads first argument as file containing urls and prints them
12/14/2015 Ruby Tutorial with Code Samples
http://www.fincher.org/tips/Languages/Ruby/ 26/31
#usage: ruby wget.rb wget.txt require 'open-uri' IO.foreach(ARGV[0]) |line| open(line) |f| print f.read
42. Example of drawing a line on a canvas in TkTk is a graphical subsystem used in languages like Perl and Tcl.
#draws a single line on a big canvas require 'tk' include Math
TkRoot.new do |root| title "Solo Line" geometry "600x600" canvas2 = TkCanvas.new(root) do |canvas| width 600 height 600 pack('side' => 'top', 'fill'=>'both', 'expand'=>'yes') points = [] end TkcLine.new(canvas2, 0,0,100,100) end Tk.mainloop
43. irb interactive rubyRuby comes with an REPL (Read Eval Print Loop) utility to let you
try ruby interactively. ("infruby.el" provides an internal shell in emacsfor irb).
C:>irb irb(main):001:0> puts "hello" puts "hello" hello nil irb(main):002:0> Object.methods Object.methods ["send", "name", "class_eval", "object_id", "new", "singleton_methods"irb(main):003:0>
44. RubyGems a ruby package installerYou can download RubyGems from http://rubyforge.org. Unzip the
files (eg, C:\opt\ruby) then install by entering:
C:>cd C:\opt\ruby\rubygems0.9.0 C:\opt\ruby\rubygems0.9.0>ruby setup.rb all
45. Ruby on RailsA. How to write a log message
You can use logger's methods "warn", "info", "error", and"fatal".
12/14/2015 Ruby Tutorial with Code Samples
http://www.fincher.org/tips/Languages/Ruby/ 27/31
logger.info("request.remote_ip"+request.remote_ip);
B. Field names ending with "_at" are assumed to be datetimefields and are filled in automagically by rails for ActiveRecordobjects. The suffix "_on" are assumed to be dates.
C. Consoleto dubug applications it's convenient to use the console script
myapp>ruby script/console
D. debug methodYou can use the debug() method inside web pages to dump
info about an object.
<p>Thanks for visiting</p> <%= debug(@myobject) %>
E. How to Freeze a versionSince your hosting company may upgrade the rails version
you need to "freeze" the current version. The following copies allthe 1.2.6 libraries from the shared directory to your own privateone.
rake rails:freeze:edge TAG=rel_126
F. Active record notesa. Find all records meeting a criteria
def self.suitable_jokes(sort_key) if sort_key == "Newest" find(:all, :conditions => "suitable = \"1\"", :order => "entry_date DESC" ) elsif sort_key == "Worst" find(:all, :conditions => "suitable = \"1\"", :order => "entry_date ASC" ) else find(:all, :conditions => "suitable = \"1\"", :order => "current_rating DESC" ) end end
The first argument to find can also be ":first" or ":last".b. Find the count of records meeting a criteria
12/14/2015 Ruby Tutorial with Code Samples
http://www.fincher.org/tips/Languages/Ruby/ 28/31
def self.waiting_jokes() count("suitable = \"0\"") end def self.total() count("suitable = \"1\"") end
Find the total number of items
count = Joke.count
Find the total number of items meeting a criteria
count = Joke.count(["suitable = \"1\""])
c. PaginationThe ":limit" and ":offset" options allow easy pagination.To return the fifth page of items use the following:
find(:all, :conditions => "suitable = \"1\"", :order => "current_rating DESC", :limit => 10, :offset => 40 )
d. Use raw SQL and return two values
def getAverageRatingAndCount record = Rating.find_by_sql(["select count(*) as count,avg(rating) as average from ratings WHERE joke_id = ?" return record[0].average.to_f , record[0].count.to_i end
e. The "create" method in ActiveRecord will do "new" and"save" operations simultanously.
mydog = Dog.create( :name => "Fido" :breed => "Collie" )
G. WatirWatir is a GUI testing tool written in Ruby. Here is a script to
open Google and search for pictures of kittens.
require "watir" ie = Watir::IE.new #create an object to drive the browser ie.goto "http://www.google.com/" ie.url == "http://www.google.com/"
12/14/2015 Ruby Tutorial with Code Samples
http://www.fincher.org/tips/Languages/Ruby/ 29/31
ie.link(:text, "Images").flash #flash the item text "Images" ie.link(:text, "Images").click #click on the link to the images search pageie.text.include? "The most comprehensive image search on the web"searchTerm = "kittens" #set a variable to hold our search term ie.text_field(:name, "q").set(searchTerm) # q is the name of the search fieldie.button(:name, "btnG").click # "btnG" is the name of the google buttonif ie.contains_text(searchTerm) puts "Test Passed. Found the test string: #searchTerm. Actual Results match Expected Results."else puts "Test Failed! Could not find: #searchTerm" end
H. Selecting a JavaScript popup boxstolen from http://wiki.openqa.org/display/WTR/FAQ
#Watir script to show clicking a JavaScript popup box require "watir" require 'watir\contrib\enabled_popup' require 'startClicker' require 'net/http' require 'net/https'
$ie = Watir::IE.new #create an object to drive the browser $ie.goto "http://mydomain.com/ListGroups.aspx" if $ie.contains_text("Log In") $ie.text_field(:name, "Login1$UserName").set("fincherm") $ie.text_field(:name, "Login1$Password").set("mitch") $ie.button(:name, "Login1$LoginButton").click end $ie.link(:text, "Baseline").click $ie.link(:text, "MoonManC").click def setDdlPriority(priority) ddlPriority = $ie.select_list( :name , /ddlPriority/) puts ddlPriority ddlPriority.select(priority) puts ddlPriority $ie.button(:name, "ctl00$btnSave").click_no_wait startClicker( "OK", 4 , "User Input" ) sleep 1 end setDdlPriority("2") setDdlPriority("9")
startClicker.rb:
#method startClicker from http://wiki.openqa.org/display/WTR/FAQ def startClicker( button , waitTime= 9, user_input=nil ) # get a handle if one exists hwnd = $ie.enabled_popup(waitTime) if (hwnd) # yes there is a popup w = WinClicker.new if ( user_input ) w.setTextValueForFileNameField( hwnd, "#user_input" end # I put this in to see the text being input it is not necessary to work sleep 3
12/14/2015 Ruby Tutorial with Code Samples
http://www.fincher.org/tips/Languages/Ruby/ 30/31
# "OK" or whatever the name on the button is w.clickWindowsButton_hwnd( hwnd, "#button" ) # # this is just cleanup w=nil end end
I. How to use Watir with NUnitHere is an example of connecting it to NUnit.
using System; using System.Diagnostics; using System.Text.RegularExpressions; using NUnit.Framework;
namespace SurveyDirector.Test.Watir /// <summary> /// from http://www.hanselman.com/blog/IntegratingRubyAndWatirWithNUnit.aspx /// with small hacks from Liz Buenker /// </summary> public class WatirAssert public static void TestPassed(string rubyFileName, string string output = String.Empty; using (Process p = new Process()) p.StartInfo.UseShellExecute = false; p.StartInfo.RedirectStandardOutput = true; p.StartInfo.FileName = "ruby.exe"; p.StartInfo.Arguments = rubyFileName + " -b" p.StartInfo.WorkingDirectory = directoryPath p.Start(); output = p.StandardOutput.ReadToEnd(); p.WaitForExit(); Console.Write(output); Trace.Write(output); Regex reg = new Regex(@"(?<tests>\d+) tests, (?<assertions> Match m = reg.Match(output); try int tests = int.Parse(m.Groups["tests"].Value); int assertions = int.Parse(m.Groups["assertions" int failures = int.Parse(m.Groups["failures"].Value int errors = int.Parse(m.Groups["errors"].Value if (tests > 0 && failures > 0) Assert.Fail(String.Format("WatirAssert: Failures 0" else if (errors > 0) Assert.Fail(String.Format("WatirAssert: Errors 0" catch (Exception e)
12/14/2015 Ruby Tutorial with Code Samples
http://www.fincher.org/tips/Languages/Ruby/ 31/31
Assert.Fail("WatirAssert EXCEPTION: " + e.ToString
The above code would be used by something like this:
using System; using NUnit.Framework;
namespace SurveyDirector.Test.Watir [TestFixture] public class WatirTest private static readonly string testDir = Utilities.Properties public WatirTest() [Test] public void Sd01Test() WatirAssert.TestPassed("sd01_test.rb",testDir); [Test] public void Sd02Test() WatirAssert.TestPassed("sd02_test.rb",testDir);
46. Ruby Quotes:
"Ruby is a language for clever people." Matz "Ruby is the perlification of Lisp." Matz "Type Declarations are the Maginot line of programming." MitchFincher