Download - Ruby Tutorial for Beginners

Transcript
  • 8/3/2019 Ruby Tutorial for Beginners

    1/27

    Ruby for the Attention Deficit Disorder Programmer - let's start learning Ruby fast!

    "Java is a pair of scissors, Ruby is a chainsaw."

    1. Install Ruby

    For windows you can download Ruby from http://rubyforge.org/frs/?group_id=167 for

    Linux try http://www.rpmfind.net.

    2. Our first program

    Enter 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, andstrings like %s.",3.14156,"me")

    This produces:

    puts workswith line breaks.print works with no line breaks.

    printf formats numbers like 3.14, and strings likeme.

    4. Reading from the Console

    Use "gets"

    http://rubyforge.org/frs/?group_id=167http://www.rpmfind.net/http://rubyforge.org/frs/?group_id=167http://www.rpmfind.net/
  • 8/3/2019 Ruby Tutorial for Beginners

    2/27

    puts "What is your name?"$name = STDIN.getsputs "Hi "+$name

    5. Functions1. Our first Ruby function

    'def' starts the definition of a method, and 'end' ends it - no cute little curly braces.

    def welcome(name)puts "howdy #{name}" # inside double quotes, #{ } will

    evaluate the variableendwelcome("nana") # traditional parens

    This Produces:

    howdy nana

    2. Parentheses are optional3. def welcome(name)4. puts "howdy #{name}" # inside double quotes, #{ } will

    evaluate the variable5. end6. welcome "visitor" #look, ma, no parentheses

    This Produces:

    howdy visitor

    The same is true of methods without arguments

    "hello".upcase() => "HELLO""hello".upcase => "HELLO"

    7. How to return values from a function

    We can use the faithful 'return'

    def multiply(a,b)product = a * breturn product

    endputs multiply(2,3) =>6

    Oddly enough you can leave out the "return" statement, and Ruby will helpfullyreturn the last expression:

    def mult(a,b)product = a * b

    endputs mult(2,3)

    or even simpler, leave out "product" and ruby returns the contents of the last

    expression:

    def mult(a,b)a * b

  • 8/3/2019 Ruby Tutorial for Beginners

    3/27

    endputs mult(3,3) =>9

    8. Optional argument values

    Ruby lets you assign values to arguments which may, or may not be supplied asshown below:

    def test(a=1,b=2,c=a+b)puts "#{a},#{b},#{c}"

    endtest => 1,2,3test 5 => 5,2,7test 4, 6 => 4,6,10test 3, 4, 6 => 3,4,6

    9. Extra arguments

    Extra arguments are gathered into the last variable if preceded with a "*". ("each"

    is an iterator that loops over its members).

    def test(a=1,b=2,*c)puts "#{a},#{b}"c.each{|x| print " #{x}, "} # We will learn about "each" very

    soon. I promise.endtest 3, 6, 9, 12, 15, 18

    This produces:

    3,6

    9, 12, 15, 18,

    10. Multiple return values11. def getCostAndMpg12. cost = 30000 # some fancy db calls go here13. mpg = 3014. return cost,mpg15. end16. AltimaCost, AltimaMpg = getCostAndMpg17. puts "AltimaCost = #{AltimaCost}, AltimaMpg = #{AltimaMpg}"

    Produces:

    AltimaCost = 30000, AltimaMpg = 30

    6. Open Classes

    You can add methods to existing library classes. For example, in C# 2.0, Microsoft addedthe 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 decide you need a newstring function, you can add it yourself.

    class Stringdef NullOrEmpty?(self == nil || self == "")end

  • 8/3/2019 Ruby Tutorial for Beginners

    4/27

    endputs "test".NullOrEmpty?puts "".NullOrEmpty?

    Is this way cool? Yes. Is this very dangerous? Yes. Remember, Ruby is a chainsaw.

    7. Variable naming

    Ok, let's slow down and learn some basics about variable names

    1. Global variables start with '$'2. Class variables start with '@@'3. Instance variables start with '@'4. Local variables, method names, and method parameters start with a lower case

    letter5. Class names, module names and constants start with an uppercase letter6. Variables names are composed of letters, numbers and underscores7. Method names may end with "?", "!", or "=". Methods ending with a "?" imply a

    boolean operation (eg, "instance_of?"). Methods ending with "!" imply somethingdangerous, like strings being modified in place (eg, "upcase!")

    8. Interesting tidbits about Ruby,1. '#' is the line comment character, all characters after this are ignored. Confusingly

    '#' can appear within quotes with a different meaning.2. No semi-colons are needed to end lines, but may be used to separate statements on

    the same line3. A backslash (\) at the end of a line is used for continuation4. Indenting is not significant, unlike python5. Types of variables do not need to be declared6. Lines between =begin and =end are ignored7. Lines following "__END__" on its own line with no white space, are ignored8. A tiny demonstration of these:9. # sample program showing special characters like comments10. # I'm a comment line11. a = 1 #notice no semicolon and no type declaration12. b = 2; c = 3 #notice two statements on one line13. name = "Abraham \14. Lincoln" # a line continued by trailing \15. puts "#{name}"16. =begin17. I'm ignored.18. So am I.

    19. =end20. puts "goodbye"21. __END__22. 123. 224. 325. 426. Abraham Lincoln27. goodbye

    9. Variable Types

    In Ruby, variables don't have a specific type associated with them. All variables areobjects, so we only play with pointers to those objects, and those pointers are typeagnostic.

    10. bat = "Louisville slugger"

  • 8/3/2019 Ruby Tutorial for Beginners

    5/27

    11. bat = 1.23

    12.13. Quotes

    Like 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 typical values. The #{name} construct is convertedto its value.

    With single quotes, no special characters are interpreted.

    Examples:

    name="Mike"puts "hi #{name}" =>hi Mikeputs "hi\n #{name}" => hi (carriage return)Mikeputs '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

    14. Objects

    A 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 ...

    15. Big Numbers

    Ruby automatically increases the precision of variables

    for i in 1..1000puts "2 ** #{i} = #{2**i}"

    end

    Produces:

    2 ** 1 = 22 ** 2 = 42 ** 3 = 82 ** 4 = 162 ** 5 = 322 ** 6 = 642 ** 7 = 1282 ** 8 = 256

  • 8/3/2019 Ruby Tutorial for Beginners

    6/27

    2 ** 9 = 5122 ** 10 = 1024...2 ** 1000 =107150860718626732094842504906000181056140481170553360744375038837035105112493612249319837881569585812759467291755314682518714528569231404359845775746985748039345677748242309854210746050623711418779541821530464749835819412673987675591655439460770629145711964776865421676604298316526

    24386837205668069376

    Ruby will increase the precision of the number, or decrease it as needed:

    x = 1000000puts "#{x} "+x.class.to_s => 1000000 Fixnumx = x * xputs "#{x} "+x.class.to_s => 1000000000000 Bignumx = x / 1000000puts "#{x} "+x.class.to_s => 1000000 Fixnum

    16. Parallel Assignment

    You can swap the values in variables without the use of a temp variable. Remember yourfirst programming class: Swap the values in "i" and "j"? You had to use a "t" variable tostore one of the values first. Not needed in Ruby.

    i = 0j = 1puts "i = #{i}, j=#{j}"i,j = j,iputs "i = #{i}, j=#{j}"

    Produces:

    i = 0, j=1i = 1, j=0

    17. Collections1. Arrays

    1. An array of known objects can be created by enclosing them in squarebrackets.

    2. nums = [1, 2.0, "three"]3. puts nums[2] => three

    Ruby arrays, like all right-thinking collections, are zero based.

    4. You can use negative indexes to start from the end of the array5. nums = [1, 2.0, "three", "four"]6. puts nums[-1] => four

    Using "-1" is so much more concise than "nums[nums.length()-1]".

    7. You can even use the handy "first" and "last" methods.8. [1,2,3].last => 39. [1,2,3].first => 1

    10. length

    To get the count, or size, of an array, use the "length" method.

  • 8/3/2019 Ruby Tutorial for Beginners

    7/27

    mystuff = ["tivo","nokia", "ipaq"] # make a string arrayputs mystuff.length => 3

    11. %w shortcut

    Since many arrays are composed of single words and all those commas andquote marks are troublesome, Ruby provides a handy shortcut, %w:

    mystuff = %w{tivo nokia ipaq} # make a string array

    12. inspect

    To look at contents of an object use the "inspect" method. Even moreconvenient is to use "p" as a shorthand for "puts obj.inspect"

    myarray = [1,2,5,7,11]puts myarrayputs myarray.inspectp myarray

    Produces:

    125711[1, 2, 5, 7, 11][1, 2, 5, 7, 11]

    13. Arrays can act like queues and sets14. # & is the intersection operator15. puts [1,2,3] & [3,4,5] # prints 316.17. # + is the addition operator18. puts [1,2,3]+ [3,4,5] # prints 1,2,3,3,4,519.20. # - removes items from the first array that appear in

    the second21. puts [1,2,3] - [3,4,5] # prints 1,222.23. # pop returns the last element and removes it from the

    array24. alpha = ["a","b","c","d","e","f"]25. puts "pop="+alpha.pop # pop=f26. puts alpha.inspect # ["a", "b", "c", "d", "e"]27.28. # push appends elements to the end of an array29. alpha = ["a","b","c"]30. alpha.push("x","y","z")31. puts alpha.inspect # ["a", "b", "c", "x", "y",

    "z"]32.33. # shift returns the first element and removes it from

    the array34. alpha = ["a","b","c","d","e","f"]35. puts "shift="+alpha.shift # shift=a36. puts alpha.inspect # ["b", "c", "d", "e", "f"]37.38. # unshift appends elements to the beginning of an array39. alpha = ["a","b","c"]

  • 8/3/2019 Ruby Tutorial for Beginners

    8/27

    40. alpha.unshift("x","y","z")41. puts alpha.inspect # ["x", "y", "z", "a", "b",

    "c"]

    2. Hashes

    This type of collection is also called a dictionary or an associative array.

    1. Simple hash of cars and their makers2. cars = {3. 'altima' => 'nissan',4. 'camry' => 'toyota',5. 'rx7' => 'mazda'6. }7. puts cars['rx7'] => mazda

    8. You can create a hash and fill it dynamically9. dict = {} # create a new dictionary10. dict['H'] = 'Hydrogen' #associate the key 'H' to the

    value 'Hydrogen'11. dict['He'] = 'Helium'12. dict['Li'] = 'Lithium'

    13. p dict['H'] # prints "Hydrogen"14. p dict.length # prints 315. p dict.values # prints ["Lithium", "Helium",

    "Hydrogen"]16. p dict.keys # prints ["Li", "He", "H"]17. p dict # prints {"Li"=>"Lithium",

    "He"=>"Helium", "H"=>"Hydrogen"}

    18. Hash[]

    You can also create Hashes with square brackets by prefixing with "Hash":

    toppings =

    Hash["pancakes","syrup","Pizza","Pepper","Cereal","Sugar"]puts toppings.inspect

    Produces:

    {"Pizza"=>"Pepper", "Cereal"=>"Sugar", "pancakes"=>"syrup"}

    19. each

    The "each" method is a wonderful way to iterate over the keys

    toppings =Hash["pancakes","syrup","Pizza","Pepper","Cereal","Sugar"]toppings.each{|key, value| puts "#{key} points to #{value}"}

    Produces:

    Pizza points to PepperCereal points to Sugarpancakes points to syrup

    20. select

    The "select" method populates a new array with members which meet acriteria

  • 8/3/2019 Ruby Tutorial for Beginners

    9/27

    salaries =Hash["bob",10.9,"larry",7.5,"jimmy",6.0,"jerry",6.5]salaries.inspectmySalaryArray = salaries.select{|name,salary| salary > 7.0}puts mySalaryArray.inspect => [["larry", 7.5], ["bob",10.9]]

    3. Ranges

    Ranges are composed of expr..expr or expr...expr. Two dots includes the lastelement, three dots excludes it.

    ('a'..'g').each{ |letter| puts letter }

    Produces:

    abc

    defg(1...3).each{ |num| puts num }

    Produces only two numbers since "..." does not include the last element.:

    12

    18. Control Statements

    1. if In an "if" statement anything but the two special values, "false" and "nil" areconsidered true. Even zero is true for all you C/C++ programmers.

    2. income = 30000.003. if income < 100004. rate = 0.025. elsif income < 300006. rate = 0.287. else8. rate = 0.59. end10. puts rate

    11. case12. grade = 1013. school = case grade14. when 0..515. "elementary"16. when 6..817. "middle school"18. when 9..1219. "high school"20. else21. "college"22. end23. puts "grade #{grade} is in #{school}"

    24. for

    25. for i in 1..426. puts "hi #{i}"27. end

  • 8/3/2019 Ruby Tutorial for Beginners

    10/27

    The ranges can of course have variables

    top = 6for i in 1..topputs "hi #{i}"end

    28. exit29. lines = IO.readlines("data.txt")30. if lines.length < 10031. exit 232. end33. puts lines.length

    34. loop

    iterates over code until a "break" or eternity ends

    i=0loop do

    break if i > 5puts ii += 1

    end

    19. Statement modifiers

    These are just syntatic sugar.

    1. if

    The "if" clause may be placed at the end of a statement

    balance = -10.0puts "Bankrupt" if balance < 0.0

    2. unless

    "unless" is placed at the end of a statement

    balance = -10.0puts "Bankrupt" unless balance > 0.0

    3. while

    "while" may be after its block

    f=2puts f=f+2 while f < 10=>4=>6=>8=>10

    20. Iterators

    1. while2. i = 03. while i < 54. i = i+1

  • 8/3/2019 Ruby Tutorial for Beginners

    11/27

    5. puts i6. end

    7. "times"8. n = 109. n.times { |i| print i}

    Produces:

    0123456789

    10. "each"11. animals = %w(lions tigers bears)12. animals.each{|kind| print kind}13. lionstigersbears

    14. "each" with ranges15. ('m'..'z').each {|ch| print ch}16. mnopqrstuvwxyz

    17. "upto"18. n=0 ; max=7

    19. n.upto(max) {|num| print num}20. 01234567

    21. You gotta have class.1. Classes

    Class definitions start with "class" and end with "end". Remember that class namesstart with a capital letter. Notice the syntax is "object.new" for creating an objectand that the "initialize" method contains code normally found in the constructor.Here's a small example:

    class Persondef initialize(fname, lname)

    @fname = fname@lname = lnameend

    endperson = Person.new("Augustus","Bondi")print person

    Produces:

    #

    which is true, but not helpful.

    2. The "ToString" method, to_s3. class Person4. def initialize(fname, lname)5. @fname = fname6. @lname = lname7. end8. def to_s9. "Person: #@fname #@lname"10. end11. end12. person = Person.new("Augustus","Bondi")

    13. print person

    Produces:

  • 8/3/2019 Ruby Tutorial for Beginners

    12/27

    Person: Augustus Bondi

    14. Subclassing

    In Ruby subclassing is done with the "

  • 8/3/2019 Ruby Tutorial for Beginners

    13/27

    endemployee = Employee.new("Augustus","Bondi","CFO")puts employeeputs employee.fnameemployee.position = "CEO"puts employee

    15. Virtual Attributes16. class Employee < Person17. def initialize(fname, lname, position)18. super(fname,lname)19. @position = position20. end21. def to_s22. super + ", #@position"23. end24. attr_writer :position25. def etype26. if @position == "CEO" || @position == "CFO"27. "executive"28. else

    29. "staff"30. end31. end32. end33. employee = Employee.new("Augustus","Bondi","CFO")34. employee.position = "CEO"35. puts employee.etype => executive36. employee.position = "Engineer"37. puts employee.etype => staff

    22. Regular Expressions

    Strings can be compared to a regular expression with "=~". Regular expressions are

    surrounded by "//" or "%r{}". Anything but the two special values, "false" and "nil" areconsidered true.

    Expression Result Description

    /a/ =~ "All Gaul is divided into threeparts"

    5 finds the first "a" at position 5

    %r{a} =~ "All Gaul is divided into threeparts"

    5 same thing with alternate syntax

    /ree/ =~ "All Gaul is divided into three

    parts"

    27 finds "ree" at position 27

    /^a/ =~ "All Gaul is divided into threeparts"

    nil"^" implies at the beginning of a line. nilis false.

    /^A/ =~ "All Gaul is divided into threeparts"

    0 case-sensitive, remember that "0" is true

    /s$/ =~ "All Gaul is divided into threeparts"

    35 "$" implies at the end of a line

    /p.r/ =~ "All Gaul is divided into threeparts"

    31 "." matches any character

    23. Blocks

    And now to one of the coolest things about Ruby - blocks. Blocks are nameless chunks ofcode that may be passed as an argument to a function.

  • 8/3/2019 Ruby Tutorial for Beginners

    14/27

    1. Simple Example2. def whereisit3. yield4. yield5. yield6. end7. 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 called a block. That chunkof code is passed to the method "whereisit" and executed each time the "yield"statement is executed. You can think of the "yield" being replaced by the block ofcode.

    8. Blocks can take arguments

    Here the method "cubes" takes the max value.

    def cubes(max)i=1while i < max

    yield i**3i += 1

    endendcubes(8) { |x| print x, ", "} => 1, 8, 27, 64, 125, 216, 343,

    sum = 0cubes(8) { |y| sum += y}print "\nsum=",sum => sum=784product = 1cubes(8) { |z| product *= z}print "\nproduct=",product => product=128024064000

    Think of the "yield i**3" in the function cubes as being replaced with the block, '|x|print x, ", "'. The value following the "yield" is passed as the value "x" to the block.

    9. Multiple arguments may be passed to blocks.10. def employee(empId)

    11. #next 2 lines simulated from calling a database on theempId

    12. lastname = "Croton"13. firstname = "Milo"14. yield lastname,firstname #multiple arguments sent to

    block15. end16. employee(4) { |last,first| print "employee ",": ",first, "

    ",last}

    Produces:

    employee : Milo Croton

    17. Local variables can be shared with a block

  • 8/3/2019 Ruby Tutorial for Beginners

    15/27

    Even though rate is a local variable, it is used inside the block.

    def tip(mealCost)yield mealCost

    endrate = 0.15mytip = tip(10.0) { |cost| cost * rate }print "tip should be: ",mytip

    Produces:

    tip should be: 1.5

    18. Blocks are built in to many objects in ruby1. each

    iterates through each item of a collection

    [1,2,3,4].each{|x| print x**2," "}

    Produces:

    1 4 9 16

    2. detect

    returns the first item matching a logical expression

    numbers = [1,3,5,8,10,14]firstDoubleDigit = numbers.detect {|x| x > 9}

    print firstDoubleDigit => 10

    3. select

    returns 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]

    4. collect

    returns 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", "QUICK", "BROWN", "LOX"]

    5. inject

    "inject" is the "fold"or "reducer" function in Ruby. "inject" loops over anenumerable and performs an operation on each object and returns a singlevalue.

    primes = [1,3,5,7,11,13];#using "inject" to sum. We pass in "0" as the initial value

    http://en.wikipedia.org/wiki/Fold_(higher-order_function)http://en.wikipedia.org/wiki/Fold_(higher-order_function)http://en.wikipedia.org/wiki/Fold_(higher-order_function)
  • 8/3/2019 Ruby Tutorial for Beginners

    16/27

    sum = primes.inject(0){|cummulative,prime|cummulative+prime}puts sum =>40#we pass in no initial value, so inject uses the firstelementproduct = primes.inject{|cummulative,prime|cummulative*prime}puts product =>15015

    #just for fun let's sum all the numbers from 1 to, oh, say amillionsum = (1..1000000).inject(0){|cummulative,n| cummulative+n}puts sum =>500000500000#you can do interesting things like build hasheshash = primes.inject({}) { |s,e| s.merge( { e.to_s => e } )}p hash # => {"11"=>11, "7"=>7, "13"=>13, "1"=>1, "3"=>3,"5"=>5}

    24. File I/O1. Read an entire file into a string2. file = File.new( "t1.php" )3. mytext = file.read

    4. Read an entire file into an array of lines5. lines = IO.readlines("data.txt")6. puts lines[0] #prints the first line

    7. Read a file line by line8. file = File.open("res.txt")9. while line = file.gets10. puts line11. end

    Or you can use the IO class

    IO.foreach("data.txt") { |line| puts line }

    12. Read a file line by line

    You should ensure the file is closed as well.

    beginfile = File.open("res.txt")

    while line = file.getsputs line

    endensure

    file.closeend

    13. Read only a few bytes at a time

    The following snippet of code reads a file which may have no line breaks andchops it into 80 character lines

    require 'readbytes'file = File.new( "C:/installs/myapp_log.xml" )while bytes = file.readbytes(80)

    print bytes+"\r\n"endfile.close

  • 8/3/2019 Ruby Tutorial for Beginners

    17/27

    14. Reads a large XML file and inserts line breaks

    Uses TruncatedDataError to grab the last few slacker bytes from the end.

    # reads an xml file without line breaks and puts a line breakbefore each '

  • 8/3/2019 Ruby Tutorial for Beginners

    18/27

    program ending

    34. converting between strings and ints

    Use the to_i and to_s methods

    "3".to_i #return an integer

    3.to_s # returns a string

    35. Using XML Dom Parser

    REXML 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 filedoc.elements.each("//div[@class='entry']") { |element| puts element }

    36. Run a few lines directly from the command line with the "-e" option37. c:\home\mfincher>ruby -e 'sleep 2'38. c:\home\mfincher>ruby -e 'puts 3*4'39. 1240. c:\home\mfincher>ruby -e 'puts 3*4; puts 4*4'41. 1242. 16

    43. Editing files in place

    Ruby offers a simple way to make a string substitution in many files all at once with asingle line of code. The "-p" option loops over the files, the "-i" is the backup extension.

    With this command we are changing all the documentation from version 1.5 to 1.6, but theoriginal files are renamed to ".bak".

    C:\home\mfincher\ruby>more v2.txtRegarding 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.txtRegarding version 1.6 .......

    version 1.6 is easy to install

    C:\home\mfincher\ruby>more v2.txt.bakRegarding version 1.5 .......version 1.5 is easy to install

    44. Example of printing duplicate lines in sorted file.45. #prints duplicate lines in sorted files in the file passed in as first

    arg46. file = File.open(ARGV[0])47. lastLine = ""48. counter = 049. while line = file.gets50. counter += 151. if lastLine == line52. puts "#{counter-1}: #{line}#{counter}: #{line}\r\n"

  • 8/3/2019 Ruby Tutorial for Beginners

    19/27

    53. end54. lastLine = line55. end56. puts "done. Processed #{counter} lines"

    57. Ruby has its own interpreted shell, irb.58. C:\home\mfincher>irb59. irb(main):001:0> puts "Hello World"60. Hello World

    61. => nil62. irb(main):002:0> a=163. => 164. irb(main):003:0> a*265. => 266. irb(main):004:0>

    67. ruby can take input from stdin68. echo 'puts "hello"' | ruby

    69. to pass a string on the url it needs to be "escape"'d first.70. require 'uri'71. ...72. URI.escape("some string...")

    73. Example to remove "funny" characters from a filename

    Example of iterating over the filenames in a directory, using regular expressionsubstitution in strings, and renaming files.

    #replaces any "funny" characters in a filename in the current directorywith an underscore#if the new file name already exists, this skips it.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)

    endelseputs " it's ok."

    end}

    74. Looping over list of arguments75. ARGV.each {|f|76. puts f77. counter = 078. file = File.open(f,"r")79. ftmp = f+".tmp"80. tmp = File.open(ftmp,"w")81. while line = file.gets82. if line =~ /pid="2"/83. counter += 184. line = line.gsub(/pid="2"/,"pid=\"#{f}:#{counter}\"")

    85. puts line86. end87. tmp.print line88. end89. file.close

  • 8/3/2019 Ruby Tutorial for Beginners

    20/27

    90. tmp.close91. puts "renaming #{ftmp} to #{f}"92. File.rename(ftmp,f)93. }94.

    95. Miscellanous Commands

    Interesting string functions

    96. DateTime97. puts DateTime.now #prints 2006-11-25T14:26:15-060098. puts Date.today #prints 2006-11-2599. puts Time.now #prints Sat Nov 25 14:29:57 Central Standard Time

    2006

    100. Using 'require'

    require will let your access code from other files. 'require' looks in directories specified in$LOAD_PATH to find the files. The environmental variable RUBYLIB can be used toload paths into $LOAD_PATH.

    C:\home\mfincher\ruby>irbirb(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/site_ruby", "c:/opt/ruby/lib/ruby/1.8","c:/opt/ruby/lib/ruby/1.8/i386-mswin32", "."]=> nil

    You can put a library like 'startClicker.rb' in any of those directories and ruby will find it.

    require 'startClicker'

    101. BuiltIn Command Interpreter

    With the "eval" method you can create your own interpreter language and run it duringexecution.

    irb(main):007:0> a = 6=> 6irb(main):008:0> b = 7=> 7irb(main):009:0> eval "c=a+b"=> 13

    irb(main):010:0> puts c13

    102. Introspection with ObjectSpace

    You can find all the objects in your program of a particular type usingObjectSpace.each_object.

    class Persondef initialize(name,age)@name = name@age = age

    endattr_reader :name

    endp = Person.new("Alfred",34)

  • 8/3/2019 Ruby Tutorial for Beginners

    21/27

    p2 = Person.new("Janie",31)ObjectSpace.each_object(Person) {|s|

    puts s.name}

    Produces:

    JanieAlfred

    103. Testing

    Ruby 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 + 1assert_equal(2, s)end

    end

    104. 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#usage: ruby wget.rb wget.txtrequire 'open-uri'IO.foreach(ARGV[0]) { |line| open(line){ |f| print f.read } }

    105. Example of drawing a line on a canvas in Tk

    Tk is a graphical subsystem used in languages like Perl and Tcl.

    #draws a single line on a big canvasrequire 'tk'include Math

    TkRoot.new do |root|title "Solo Line"geometry "600x600"canvas2 = TkCanvas.new(root) do |canvas|

    width 600height 600pack('side' => 'top', 'fill'=>'both', 'expand'=>'yes')points = []

    end

    TkcLine.new(canvas2, 0,0,100,100)endTk.mainloop

  • 8/3/2019 Ruby Tutorial for Beginners

    22/27

    106. irb - interactive ruby

    Ruby comes with an REPL (Read Eval Print Loop) utility to let you try ruby interactively.("inf-ruby.el" provides an internal shell in emacs for irb).

    C:>irbirb(main):001:0> puts "hello"

    puts "hello"hellonilirb(main):002:0> Object.methodsObject.methods["send", "name", "class_eval", "object_id", "new", "singleton_methods","__send__", "private_method_defined?", "equal?", "taint", "frozen?","instance_variable_get", "constants", "kind_of?", "to_a","instance_eval", "require", "ancestors", "const_missing", "type","instance_methods", "protected_methods", "extend","protected_method_defined?", "eql?", "public_class_method", "const_get","instance_variable_set", "hash", "is_a?", "autoload", "to_s","class_variables", "class", "tainted?", "private_methods",

    "public_instance_methods", "instance_method", "untaint","included_modules", "private_class_method", "const_set", "id", "", "===", "clone","public_methods", "protected_instance_methods", "require_gem", ">=","respond_to?", "display", "freeze", "

  • 8/3/2019 Ruby Tutorial for Beginners

    23/27

    Thanks for visiting

    5. How to Freeze a version

    Since your hosting company may upgrade the rails version you need to "freeze" thecurrent version. The following copies all the 1.2.6 libraries from the shared

    directory to your own private one.

    rake rails:freeze:edge TAG=rel_1-2-6

    6. Active record notes1. Find all records meeting a criteria2. def self.suitable_jokes(sort_key)3. if sort_key == "Newest"4. find(:all,5. :conditions => "suitable = \"1\"",6. :order => "entry_date DESC"7. )

    8. elsif sort_key == "Worst"9. find(:all,10. :conditions => "suitable = \"1\"",11. :order => "entry_date ASC"12. )13. else14. find(:all,15. :conditions => "suitable = \"1\"",16. :order => "current_rating DESC"17. )18. end19. end

    The first argument to find can also be ":first" or ":last".

    20. Find the count of records meeting a criteria21. def self.waiting_jokes()22. count("suitable = \"0\"")23. end24. def self.total()25. count("suitable = \"1\"")26. end

    Find the total number of items

    count = Joke.count

    Find the total number of items meeting a criteria

    count = Joke.count(["suitable = \"1\""])

    27. Pagination

    The ":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",

  • 8/3/2019 Ruby Tutorial for Beginners

    24/27

    :limit => 10,:offset => 40

    )

    28. Use raw SQL and return two values29. def getAverageRatingAndCount30. record = Rating.find_by_sql(["select count(*) as

    count,avg(rating) as average from ratings WHERE joke_id

    = ?",id]);31. return record[0].average.to_f ,

    record[0].count.to_i32. end

    33. The "create" method in ActiveRecord will do "new" and "save" operationssimultanously.

    34. mydog = Dog.create(35. :name => "Fido"36. :breed => "Collie"37. )

    7. Watir

    Watir is a GUI testing tool written in Ruby. Here is a script to open Google andsearch for pictures of kittens.

    require "watir"ie = Watir::IE.new #create an object to drive the browserie.goto "http://www.google.com/"ie.url == "http://www.google.com/"ie.link(:text, "Images").flash #flash the item text "Images"ie.link(:text, "Images").click #click on the link to the imagessearch pageie.text.include? "The most comprehensive image search on the web"#test to make sure it worked

    searchTerm = "kittens" #set a variable to hold our search termie.text_field(:name, "q").set(searchTerm) # q is the name of thesearch fieldie.button(:name, "btnG").click # "btnG" is the name of the googlebuttonif 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

    8. Selecting a JavaScript popup box

    stolen from http://wiki.openqa.org/display/WTR/FAQ

    #Watir script to show clicking a JavaScript popup boxrequire "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

  • 8/3/2019 Ruby Tutorial for Beginners

    25/27

    $ie.link(:text, "Baseline").click$ie.link(:text, "MoonManC").clickdef setDdlPriority(priority)

    ddlPriority = $ie.select_list( :name , /ddlPriority/)puts ddlPriorityddlPriority.select(priority)puts ddlPriority$ie.button(:name, "ctl00$btnSave").click_no_wait

    startClicker( "OK", 4 , "User Input" )sleep 1

    endsetDdlPriority("2")setDdlPriority("9")

    startClicker.rb:

    #method startClicker from http://wiki.openqa.org/display/WTR/FAQdef startClicker( button , waitTime= 9, user_input=nil )# get a handle if one existshwnd = $ie.enabled_popup(waitTime)if (hwnd) # yes there is a popupw = WinClicker.newif ( user_input )w.setTextValueForFileNameField( hwnd, "#{user_input}" )

    end# I put this in to see the text being input it is not

    necessary to worksleep 3# "OK" or whatever the name on the button isw.clickWindowsButton_hwnd( hwnd, "#{button}" )## this is just cleanupw=nil

    endend

    9. How to use Watir with NUnit

    Here is an example of connecting it to NUnit.

    using System;using System.Diagnostics;using System.Text.RegularExpressions;using NUnit.Framework;

    namespace SurveyDirector.Test.Watir{

    /// /// from

    http://www.hanselman.com/blog/IntegratingRubyAndWatirWithNUnit.aspx

    /// with small hacks from Liz Buenker/// public class WatirAssert{

    public static void TestPassed(string rubyFileName, stringdirectoryPath)

    {string output = String.Empty;using (Process p = new Process()){

    p.StartInfo.UseShellExecute = false;p.StartInfo.RedirectStandardOutput = true;

    http://www.hanselman.com/blog/IntegratingRubyAndWatirWithNUnit.aspxhttp://www.hanselman.com/blog/IntegratingRubyAndWatirWithNUnit.aspxhttp://www.hanselman.com/blog/IntegratingRubyAndWatirWithNUnit.aspxhttp://www.hanselman.com/blog/IntegratingRubyAndWatirWithNUnit.aspx
  • 8/3/2019 Ruby Tutorial for Beginners

    26/27

    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(@"(?\d+) tests, (?

    \d+) assertions, (?\d+) failures, (?\d+) errors", RegexOptions.Compiled);

    Match m = reg.Match(output);try{

    int tests = int.Parse(m.Groups["tests"].Value);int assertions =

    int.Parse(m.Groups["assertions"].Value);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}", failures));}else if (errors > 0){

    Assert.Fail(String.Format("WatirAssert: Errors{0}", errors));

    }}catch (Exception e){

    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.baseDir + "\\Test\\Watir";

    public WatirTest() { }[Test]public void Sd01Test(){

    WatirAssert.TestPassed("sd01_test.rb",testDir);}[Test]

    public void Sd02Test(){

    WatirAssert.TestPassed("sd02_test.rb",testDir);}

  • 8/3/2019 Ruby Tutorial for Beginners

    27/27

    }}

    109. 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." -Mitch Fincher