Blog

  • Associated Tools

    Standard Ruby Tools

    The standard Ruby distribution contains useful tools along with the interpreter and standard libraries −

    These tools help you debug and improve your Ruby programs without spending much effort. This tutorial will give you a very good start with these tools.

    • RubyGems −RubyGems is a package utility for Ruby, which installs Ruby software packages and keeps them up-to-date.
    • Ruby Debugger −To help deal with bugs, the standard distribution of Ruby includes a debugger. This is very similar to gdb utility, which can be used to debug complex programs.
    • Interactive Ruby (irb) −irb (Interactive Ruby) was developed by Keiju Ishitsuka. It allows you to enter commands at the prompt and have the interpreter respond as if you were executing a program. irb is useful to experiment with or to explore Ruby.
    • Ruby Profiler −Ruby profiler helps you to improve the performance of a slow program by finding the bottleneck.

    Additional Ruby Tools

    There are other useful tools that don’t come bundled with the Ruby standard distribution. However, you do need to install them yourself.

    • eRuby: Embeded Ruby −eRuby stands for embedded Ruby. It’s a tool that embeds fragments of Ruby code in other files, such as HTML files similar to ASP, JSP and PHP.
    • ri: Ruby Interactive Reference −When you have a question about the behavior of a certain method, you can invoke ri to read the brief explanation of the method.

    For more information on Ruby tool and resources, have a look at Ruby Useful Resources.

  • Predefined Constants

    The following table lists all the Ruby’s Predefined Constants −

    NOTE − TRUE, FALSE, and NIL are backward-compatible. It’s preferable to use true, false, and nil.

    Sr.No.Constant Name & Description
    1TRUESynonym for true.
    2FALSESynonym for false.
    3NILSynonym for nil.
    4ARGFAn object providing access to virtual concatenation of files passed as command-line arguments or standard input if there are no command-line arguments. A synonym for &dollar;<.
    5ARGVAn array containing the command-line arguments passed to the program. A synonym for &dollar;*.
    6DATAAn input stream for reading the lines of code following the __END__ directive. Not defined if __END__ isn’t present in code.
    7ENVA hash-like object containing the program’s environment variables. ENV can be handled as a hash.
    8RUBY_PLATFORMA string indicating the platform of the Ruby interpreter.
    9RUBY_RELEASE_DATEA string indicating the release date of the Ruby interpreter
    10RUBY_VERSIONA string indicating the version of the Ruby interpreter.
    11STDERRStandard error output stream. Default value of &dollar;stderr.
    12STDINStandard input stream. Default value of &dollar;stdin.
    13STDOUTStandard output stream. Default value of &dollar;stdout.
    14TOPLEVEL_BINDINGA binding object at Ruby’s top level.
  • Predefined Variables

    Ruby’s predefined variables affect the behavior of the entire program, so their use in libraries is not recommended.

    The values in most predefined variables can be accessed by alternative means.

    Following table lists all the Ruby’s predefined variables.

    Sr.No.Variable Name & Description
    1&dollar;!The last exception object raised. The exception object can also be accessed using => in rescue clause.
    2&dollar;&commat;The stack backtrace for the last exception raised. The stack backtrace information can retrieved by Exception#backtrace method of the last exception.
    3&dollar;/The input record separator (newline by default). gets, readline, etc., take their input record separator as optional argument.
    4&dollar;\The output record separator (nil by default).
    5&dollar;,The output separator between the arguments to print and Array#join (nil by default). You can specify separator explicitly to Array#join.
    6&dollar;;The default separator for split (nil by default). You can specify separator explicitly for String#split.
    7&dollar;.The number of the last line read from the current input file. Equivalent to ARGF.lineno.
    8&dollar;<Synonym for ARGF.
    9&dollar;>Synonym for $defout.
    10&dollar;0The name of the current Ruby program being executed.
    11&dollar;&dollar;The process pid of the current Ruby program being executed.
    12&dollar;?The exit status of the last process terminated.
    13&dollar;:Synonym for $LOAD_PATH.
    14&dollar;DEBUGTrue if the -d or –debug command-line option is specified.
    15&dollar;defoutThe destination output for print and printf ($stdout by default).
    16&dollar;FThe variable that receives the output from split when -a is specified. This variable is set if the -a command-line option is specified along with the -p or -n option.
    17&dollar;FILENAMEThe name of the file currently being read from ARGF. Equivalent to ARGF.filename.
    18&dollar;LOAD_PATHAn array holding the directories to be searched when loading files with the load and require methods.
    19&dollar;SAFEThe security level0 → No checks are performed on externally supplied (tainted) data. (default)1 → Potentially dangerous operations using tainted data are forbidden.2 → Potentially dangerous operations on processes and files are forbidden.3 → All newly created objects are considered tainted.4 → Modification of global data is forbidden.
    20&dollar;stdinStandard input (STDIN by default).
    21&dollar;stdoutStandard output (STDOUT by default).
    22&dollar;stderrStandard error (STDERR by default).
    23&dollar;VERBOSETrue if the -v, -w, or –verbose command-line option is specified.
    24&dollar;- xThe value of interpreter option -x (x=0, a, d, F, i, K, l, p, v). These options are listed below
    25&dollar;-0The value of interpreter option -x and alias of $/.
    26&dollar;-aThe value of interpreter option -x and true if option -a is set. Read-only.
    27&dollar;-dThe value of interpreter option -x and alias of $DEBUG
    28&dollar;-FThe value of interpreter option -x and alias of $;.
    29&dollar;-iThe value of interpreter option -x and in in-place-edit mode, holds the extension, otherwise nil. Can enable or disable in-place-edit mode.
    30&dollar;-IThe value of interpreter option -x and alias of $:.
    31&dollar;-lThe value of interpreter option -x and true if option -lis set. Read-only.
    32&dollar;-pThe value of interpreter option -x and true if option -pis set. Read-only.
    33&dollar;_The local variable, last string read by gets or readline in the current scope.
    34&dollar;~The local variable, MatchData relating to the last match. Regex#match method returns the last match information.
    35&dollar; n ($1, $2, $3…)The string matched in the nth group of the last pattern match. Equivalent to m[n], where m is a MatchData object.
    36&dollar;&The string matched in the last pattern match. Equivalent to m[0], where m is a MatchData object.
    37&dollar;`The string preceding the match in the last pattern match. Equivalent to m.pre_match, where m is a MatchData object.
    38&dollar;’The string following the match in the last pattern match. Equivalent to m.post_match, where m is a MatchData object.
    39&dollar;&plus;The string corresponding to the last successfully matched group in the last pattern match.
  • Built in Functions

    Since the Kernel module is included by Object class, its methods are available everywhere in the Ruby program. They can be called without a receiver (functional form). Therefore, they are often called functions.A complete list of Built-in Functions is given here for your reference −

    Functions for Numbers

    Here is a list of Built-in Functions related to number. They should be used as follows −

    #!/usr/bin/ruby
    
    num =12.40
    puts num.floor      # 12
    puts num +10# 22.40
    puts num.integer?# false  as num is a float.

    This will produce the following result −

    12
    22.4
    false
    

    Assuming,nis a number −

    Functions for Float

    Here is a list of Ruby Built-in functions especially for float numbers. Assuming we have a float numberf

    Functions for Math

    Here is a list of Ruby Built-in math functions −

    Conversion Field Specifier

    The function sprintf( fmt[, arg…]) and format( fmt[, arg…]) returns a string in which arg is formatted according to fmt. Formatting specifications are essentially the same as those for sprintf in the C programming language. Conversion specifiers (% followed by conversion field specifier) in fmt are replaced by formatted string of corresponding argument.The following conversion specifiers are supported by Ruby’s format −

    Following is the usage example −

    #!/usr/bin/ruby
    
    str = sprintf("%s\n","abc")# => "abc\n" (simplest form)
    puts str 
    
    str = sprintf("d=%d",42)# => "d=42" (decimal output)
    puts str 
    
    str = sprintf("%04x",255)# => "00ff" (width 4, zero padded)
    puts str 
    
    str = sprintf("%8s","hello")# => " hello" (space padded)
    puts str 
    
    str = sprintf("%.2s","hello")# => "he" (trimmed by precision)
    puts str 
    

    This will produce the following result −

    abc
    d = 42
    00ff
       hello
    he
    

    Test Function Arguments

    The function test( test, f1[, f2]) performs one of the following file tests specified by the character test. In order to improve readability, you should use File class methods (for example, File::readable?) rather than this function.Here are the file tests with one argument −File tests with two arguments are as follows −

    Following is the usage example. Assuming main.rb exist with read, write and not execute permissions −

    #!/usr/bin/ruby
    
    puts test(?r,"main.rb")# => true
    puts test(?w,"main.rb")# => true
    puts test(?x,"main.rb")# => false

    This will produce the following result −

    true
    false
    false
  • Multithreading

    Traditional programs have a single thread of execution the statements or instructions that comprise the program are executed sequentially until the program terminates.

    A multithreaded program has more than one thread of execution. Within each thread, statements are executed sequentially, but the threads themselves may be executed in parallel on a multicore CPU, for example. Often on a single CPU machine, multiple threads are not actually executed in parallel, but parallelism is simulated by interleaving the execution of the threads.

    Ruby makes it easy to write multi-threaded programs with the Thread class. Ruby threads are a lightweight and efficient way to achieve concurrency in your code.

    Creating Ruby Threads

    To start a new thread, just associate a block with a call to Thread.new. A new thread will be created to execute the code in the block, and the original thread will return from Thread.new immediately and resume execution with the next statement −

    # Thread #1 is running here
    Thread.new {
       # Thread #2 runs this code
    }
    # Thread #1 runs this code
    

    Example

    Here is an example, which shows how we can use multi-threaded Ruby program.

    #!/usr/bin/rubydeffunc1
       i =0while i<=2
    
      puts "func1 at: #{Time.now}"
      sleep(2)
      i = i&amp;plus;1endenddeffunc2
    j =0while j<=2
      puts "func2 at: #{Time.now}"
      sleep(1)
      j = j&amp;plus;1endend
    puts "Started At #{Time.now}" t1 =Thread.new{func1()} t2 =Thread.new{func2()} t1.join t2.join puts "End at #{Time.now}"

    This will produce following result −

    Started At Wed May 14 08:21:54 -0700 2008
    func1 at: Wed May 14 08:21:54 -0700 2008
    func2 at: Wed May 14 08:21:54 -0700 2008
    func2 at: Wed May 14 08:21:55 -0700 2008
    func1 at: Wed May 14 08:21:56 -0700 2008
    func2 at: Wed May 14 08:21:56 -0700 2008
    func1 at: Wed May 14 08:21:58 -0700 2008
    End at Wed May 14 08:22:00 -0700 2008
    

    Thread Lifecycle

    A new threads are created with Thread.new. You can also use the synonyms Thread.start and Thread.fork.

    There is no need to start a thread after creating it, it begins running automatically when CPU resources become available.

    The Thread class defines a number of methods to query and manipulate the thread while it is running. A thread runs the code in the block associated with the call to Thread.new and then it stops running.

    The value of the last expression in that block is the value of the thread, and can be obtained by calling the value method of the Thread object. If the thread has run to completion, then the value returns the thread’s value right away. Otherwise, the value method blocks and does not return until the thread has completed.

    The class method Thread.current returns the Thread object that represents the current thread. This allows threads to manipulate themselves. The class method Thread.main returns the Thread object that represents the main thread. This is the initial thread of execution that began when the Ruby program was started.

    You can wait for a particular thread to finish by calling that thread’s Thread.join method. The calling thread will block until the given thread is finished.

    Threads and Exceptions

    If an exception is raised in the main thread, and is not handled anywhere, the Ruby interpreter prints a message and exits. In threads, other than the main thread, unhandled exceptions cause the thread to stop running.

    If a thread t exits because of an unhandled exception, and another thread s calls t.join or t.value, then the exception that occurred in t is raised in the thread s.

    If Thread.abort_on_exception is false, the default condition, an unhandled exception simply kills the current thread and all the rest continue to run.

    If you would like any unhandled exception in any thread to cause the interpreter to exit, set the class method Thread.abort_on_exception to true.

    t = Thread.new { ... }
    t.abort_on_exception = true
    

    Thread Variables

    A thread can normally access any variables that are in scope when the thread is created. Variables local to the block of a thread are local to the thread, and are not shared.

    Thread class features a special facility that allows thread-local variables to be created and accessed by name. You simply treat the thread object as if it were a Hash, writing to elements using []= and reading them back using [].

    In this example, each thread records the current value of the variable count in a threadlocal variable with the key mycount.

    #!/usr/bin/ruby
    
    count =0
    arr =[]10.times do|i|
       arr[i]=Thread.new{
    
      sleep(rand(0)/10.0)Thread.current["mycount"]= count
      count &amp;plus;=1}end
    arr.each{|t| t.join; print t["mycount"],", "} puts "count = #{count}"

    This produces the following result −

    8, 0, 3, 7, 2, 1, 6, 5, 4, 9, count = 10
    

    The main thread waits for the subthreads to finish and then prints out the value of count captured by each.

    Thread Priorities

    The first factor that affects the thread scheduling is the thread priority: high-priority threads are scheduled before low-priority threads. More precisely, a thread will only get CPU time if there are no higher-priority threads waiting to run.

    You can set and query the priority of a Ruby Thread object with priority = and priority. A newly created thread starts at the same priority as the thread that created it. The main thread starts off at priority 0.

    There is no way to set the priority of a thread before it starts running. A thread can, however, raise or lower its own priority as the first action it takes.

    Thread Exclusion

    If two threads share access to the same data, and at least one of the threads modifies that data, you must take special care to ensure that no thread can ever see the data in an inconsistent state. This is called thread exclusion.

    Mutex is a class that implements a simple semaphore lock for mutually exclusive access to some shared resource. That is, only one thread may hold the lock at a given time. Other threads may choose to wait in line for the lock to become available, or may simply choose to get an immediate error indicating that the lock is not available.

    By placing all accesses to the shared data under control of a mutex, we ensure consistency and atomic operation. Let’s try to examples, first one without mutax and second one with mutax −

    Example without Mutax

    #!/usr/bin/rubyrequire'thread'
    
    count1 = count2 =0
    difference =0
    counter =Thread.newdo
       loop do
    
      count1 &amp;plus;=1
      count2 &amp;plus;=1endend
    spy =Thread.newdo loop do
      difference &amp;plus;=(count1 - count2).abs
    endend sleep 1 puts "count1 : #{count1}" puts "count2 : #{count2}" puts "difference : #{difference}"

    This will produce the following result −

    count1 :1583766
    count2 :1583766
    difference :0
    #!/usr/bin/rubyrequire'thread'
    mutex =Mutex.new
    
    count1 = count2 =0
    difference =0
    counter =Thread.newdo
       loop do
    
      mutex.synchronize do
         count1 &amp;plus;=1
         count2 &amp;plus;=1endendend
    spy =Thread.newdo loop do
      mutex.synchronize do
         difference &amp;plus;=(count1 - count2).abs
      endendend
    sleep 1 mutex.lock puts "count1 : #{count1}" puts "count2 : #{count2}" puts "difference : #{difference}"

    This will produce the following result −

    count1 :  696591
    count2 :  696591
    difference : 0
    

    Handling Deadlock

    When we start using Mutex objects for thread exclusion we must be careful to avoid deadlock. Deadlock is the condition that occurs when all threads are waiting to acquire a resource held by another thread. Because all threads are blocked, they cannot release the locks they hold. And because they cannot release the locks, no other thread can acquire those locks.

    This is where condition variables come into picture. A condition variable is simply a semaphore that is associated with a resource and is used within the protection of a particular mutex. When you need a resource that’s unavailable, you wait on a condition variable. That action releases the lock on the corresponding mutex. When some other thread signals that the resource is available, the original thread comes off the wait and simultaneously regains the lock on the critical region.

    Example

    #!/usr/bin/rubyrequire'thread'
    mutex =Mutex.new
    
    cv =ConditionVariable.new
    a =Thread.new{
       mutex.synchronize {
    
      puts "A: I have critical section, but will wait for cv"
      cv.wait(mutex)
      puts "A: I have critical section again! I rule!"}}
    puts "(Later, back at the ranch...)" b =Thread.new{ mutex.synchronize {
      puts "B: Now I am critical, but am done with cv"
      cv.signal
      puts "B: I am still critical, finishing up"}}
    a.join b.join

    This will produce the following result −

    A: I have critical section, but will wait for cv
    (Later, back at the ranch...)
    B: Now I am critical, but am done with cv
    B: I am still critical, finishing up
    A: I have critical section again! I rule!
    

    Thread States

    There are five possible return values corresponding to the five possible states as shown in the following table. The status method returns the state of the thread.

    Thread stateReturn value
    Runnablerun
    SleepingSleeping
    Abortingaborting
    Terminated normallyfalse
    Terminated with exceptionnil

    Thread Class Methods

    Following methods are provided by Thread class and they are applicable to all the threads available in the program. These methods will be called as using Thread class name as follows −

    Thread.abort_on_exception =true

    Here is the complete list of all the class methods available −

    Thread Instance Methods

    These methods are applicable to an instance of a thread. These methods will be called as using an instance of a Thread as follows −

    #!/usr/bin/ruby
    
    thr =Thread.newdo# Calling a class method new
       puts "In second thread"raise"Raise exception"end
    thr.join   # Calling an instance method join

    Here is the complete list of all the instance methods available −

    Sr.No.Methods & Description
    1thr[ aSymbol ]Attribute Reference – Returns the value of a thread-local variable, using either a symbol or an aSymbol name. If the specified variable does not exist, returns nil.
    2thr[ aSymbol ] =Attribute Assignment – Sets or creates the value of a thread-local variable, using either a symbol or a string.
    3thr.abort_on_exceptionReturns the status of the abort on exception condition for thr. The default is false.
    4thr.abort_on_exception=When set to true, causes all threads (including the main program) to abort if an exception is raised in thr. The process will effectively exit(0).
    5thr.alive?Returns true if thr is running or sleeping.
    6thr.exitTerminates thr and schedules another thread to be run. If this thread is already marked to be killed, exit returns the Thread. If this is the main thread, or the last thread, exits the process.
    7thr.joinThe calling thread will suspend execution and run thr. Does not return until thr exits. Any threads not joined will be killed when the main program exits.
    8thr.key?Returns true if the given string (or symbol) exists as a thread-local variable.
    9thr.killSynonym for Thread.exit.
    10thr.priorityReturns the priority of thr. Default is zero; higher-priority threads will run before lower priority threads.
    11thr.priority=Sets the priority of thr to an Integer. Higher-priority threads will run before lower priority threads.
    12thr.raise( anException )Raises an exception from thr. The caller does not have to be thr.
    13thr.runWakes up thr, making it eligible for scheduling. If not in a critical section, then invokes the scheduler.
    14thr.safe_levelReturns the safe level in effect for thr.
    15thr.statusReturns the status of thrsleep if thr is sleeping or waiting on I/O, run if thr is executing, false if thr terminated normally, and nil if thr terminated with an exception.
    16thr.stop?Returns true if thr is dead or sleeping.
    17thr.valueWaits for thr to complete via Thread.join and returns its value.
    18thr.wakeupMarks thr as eligible for scheduling, it may still remain blocked on I/O, however.

  • LDAP Tutorial

    Ruby/LDAP is an extension library for Ruby. It provides the interface to some LDAP libraries like OpenLDAP, UMich LDAP, Netscape SDK, ActiveDirectory.

    The common API for application development is described in RFC1823 and is supported by Ruby/LDAP.

    Ruby/LDAP Installation

    You can download and install a complete Ruby/LDAP package from SOURCEFORGE.NET.

    Before installing Ruby/LDAP, make sure you have the following components −

    • Ruby 1.8.x (at least 1.8.2 if you want to use ldap/control).
    • OpenLDAP, Netscape SDK, Windows 2003 or Windows XP.

    Now, you can use standard Ruby Installation method. Before starting, if you’d like to see the available options for extconf.rb, run it with ‘–help’ option.

    $ ruby extconf.rb [--with-openldap1|--with-openldap2| \
    
                   --with-netscape|--with-wldap32]
    $ make $ make install

    NOTE − If you’re building the software on Windows, you may need to use nmake instead of make.

    Establish LDAP Connection

    This is a two-step process −

    Step 1 − Create Connection Object

    Following is the syntax to create a connection to a LDAP directory.

    LDAP::Conn.new(host = 'localhost', port = LDAP_PORT)
    
    • host − This is the host ID running LDAP directory. We will take it as localhost.
    • port − This is the port being used for LDAP service. Standard LDAP ports are 636 and 389. Make sure which port is being used at your server otherwise you can use LDAP::LDAP_PORT.

    This call returns a new LDAP::Conn connection to the server, host, on port port.

    Step 2 − Binding

    This is where we usually specify the username and password we will use for the rest of the session.

    Following is the syntax to bind an LDAP connection, using the DN, dn, the credential, pwd, and the bind method, method −

    conn.bind(dn = nil, password = nil, method = LDAP::LDAP_AUTH_SIMPLE)do
    ....
    end
    

    You can use the same method without a code block. In this case, you would need to unbind the connection explicitly as follows −

    conn.bind(dn = nil, password = nil, method = LDAP::LDAP_AUTH_SIMPLE)
    ....
    conn.unbind
    

    If a code block is given, self is yielded to the block.

    We can now perform search, add, modify or delete operations inside the block of the bind method (between bind and unbind), provided we have the proper permissions.

    Example

    Assuming we are working on a local server, let’s put things together with appropriate host, domain, user id and password, etc.

    #/usr/bin/ruby -wrequire'ldap'$HOST='localhost'$PORT=LDAP::LDAP_PORT$SSLPORT=LDAP::LDAPS_PORT
    
    conn =LDAP::Conn.new($HOST,$PORT)
    conn.bind('cn = root, dc = localhost, dc = localdomain','secret')....
    conn.unbind
    

    Adding an LDAP Entry

    Adding an LDPA entry is a two step process −

    Step 1 − Creating LDAP::Mod object

    We need LDAP::Mod object pass to conn.add method to create an entry. Here is a simple syntax to create LDAP::Mod object −

    Mod.new(mod_type, attr, vals)
    
    • mod_type − One or more option LDAP_MOD_ADD, LDAP_MOD_REPLACE or LDAP_MOD_DELETE.
    • attr − should be the name of the attribute on which to operate.
    • vals − is an array of values pertaining to attr. If vals contains binary data, mod_type should be logically OR’ed (|) with LDAP_MOD_BVALUES.

    This call returns LDAP::Mod object, which can be passed to methods in the LDAP::Conn class, such as Conn#add, Conn#add_ext, Conn#modify and Conn#modify_ext.

    Step 2 − Calling conn.add Method

    Once we are ready with LDAP::Mod object, we can call conn.add method to create an entry. Here is a syntax to call this method −

    conn.add(dn, attrs)
    

    This method adds an entry with the DN, dn, and the attributes, attrs. Here, attrs should be either an array of LDAP::Mod objects or a hash of attribute/value array pairs.

    Example

    Here is a complete example, which will create two directory entries −

    #/usr/bin/ruby -wrequire'ldap'$HOST='localhost'$PORT=LDAP::LDAP_PORT$SSLPORT=LDAP::LDAPS_PORT
    
    conn =LDAP::Conn.new($HOST,$PORT)
    conn.bind('cn = root, dc = localhost, dc = localdomain','secret')
    
    conn.perror("bind")
    entry1 =[LDAP.mod(LDAP::LDAP_MOD_ADD,'objectclass',['top','domain']),LDAP.mod(LDAP::LDAP_MOD_ADD,'o',['TTSKY.NET']),LDAP.mod(LDAP::LDAP_MOD_ADD,'dc',['localhost']),]
    
    entry2 =[LDAP.mod(LDAP::LDAP_MOD_ADD,'objectclass',['top','person']),LDAP.mod(LDAP::LDAP_MOD_ADD,'cn',['Zara Ali']),LDAP.mod(LDAP::LDAP_MOD_ADD|LDAP::LDAP_MOD_BVALUES,'sn',['ttate','ALI',"zero\000zero"]),]begin
       conn.add("dc = localhost, dc = localdomain", entry1)
       conn.add("cn = Zara Ali, dc = localhost, dc =  localdomain", entry2)rescueLDAP::ResultError
       conn.perror("add")
       exit
    end
    conn.perror("add")
    conn.unbind
    

    Modifying an LDAP Entry

    Modifying an entry is similar to adding one. Just call the modify method instead of add with the attributes to modify. Here is a simple syntax of modify method.

    conn.modify(dn, mods)
    

    This method modifies an entry with the DN, dn, and the attributes, mods. Here, mods should be either an array of LDAP::Mod objects or a hash of attribute/value array pairs.

    Example

    To modify the surname of the entry, which we added in the previous section, we would write −

    #/usr/bin/ruby -wrequire'ldap'$HOST='localhost'$PORT=LDAP::LDAP_PORT$SSLPORT=LDAP::LDAPS_PORT
    
    conn =LDAP::Conn.new($HOST,$PORT)
    conn.bind('cn = root, dc = localhost, dc = localdomain','secret')
    
    conn.perror("bind")
    entry1 =[LDAP.mod(LDAP::LDAP_MOD_REPLACE,'sn',['Mohtashim']),]begin
       conn.modify("cn = Zara Ali, dc = localhost, dc = localdomain", entry1)rescueLDAP::ResultError
       conn.perror("modify")
       exit
    end
    conn.perror("modify")
    conn.unbind
    

    Deleting an LDAP Entry

    To delete an entry, call the delete method with the distinguished name as parameter. Here is a simple syntax of delete method.

    conn.delete(dn)
    

    This method deletes an entry with the DN, dn.

    Example

    To delete Zara Mohtashim entry, which we added in the previous section, we would write −

    #/usr/bin/ruby -wrequire'ldap'$HOST='localhost'$PORT=LDAP::LDAP_PORT$SSLPORT=LDAP::LDAPS_PORT
    
    conn =LDAP::Conn.new($HOST,$PORT)
    conn.bind('cn = root, dc = localhost, dc = localdomain','secret')
    
    conn.perror("bind")begin
       conn.delete("cn = Zara-Mohtashim, dc = localhost, dc = localdomain")rescueLDAP::ResultError
       conn.perror("delete")
       exit
    end
    conn.perror("delete")
    conn.unbind
    

    Modifying the Distinguished Name

    It’s not possible to modify the distinguished name of an entry with the modify method. Instead, use the modrdn method. Here is simple syntax of modrdn method −

    conn.modrdn(dn, new_rdn, delete_old_rdn)
    

    This method modifies the RDN of the entry with DN, dn, giving it the new RDN, new_rdn. If delete_old_rdn is true, the old RDN value will be deleted from the entry.

    Example

    Suppose we have the following entry −

    dn: cn =ZaraAli,dc = localhost,dc = localdomain
    cn:ZaraAli
    sn:Ali
    objectclass: person
    

    Then, we can modify its distinguished name with the following code −

    #/usr/bin/ruby -wrequire'ldap'$HOST='localhost'$PORT=LDAP::LDAP_PORT$SSLPORT=LDAP::LDAPS_PORT
    
    conn =LDAP::Conn.new($HOST,$PORT)
    conn.bind('cn = root, dc = localhost, dc = localdomain','secret')
    
    conn.perror("bind")begin
       conn.modrdn("cn = Zara Ali, dc = localhost, dc = localdomain","cn = Zara Mohtashim",true)rescueLDAP::ResultError
       conn.perror("modrdn")
       exit
    end
    conn.perror("modrdn")
    conn.unbind
    

    Performing a Search

    To perform a search on a LDAP directory, use the search method with one of the three different search modes −

    • LDAP_SCOPE_BASEM − Search only the base node.
    • LDAP_SCOPE_ONELEVEL − Search all children of the base node.
    • LDAP_SCOPE_SUBTREE − Search the whole subtree including the base node.

    Example

    Here, we are going to search the whole subtree of entry dc = localhost, dc = localdomain for person objects −

    #/usr/bin/ruby -wrequire'ldap'$HOST='localhost'$PORT=LDAP::LDAP_PORT$SSLPORT=LDAP::LDAPS_PORT
    
    base ='dc = localhost,dc = localdomain'
    scope =LDAP::LDAP_SCOPE_SUBTREE
    filter ='(objectclass = person)'
    attrs =['sn','cn']
    
    conn =LDAP::Conn.new($HOST,$PORT)
    conn.bind('cn = root, dc = localhost, dc = localdomain','secret')
    
    conn.perror("bind")begin
       conn.search(base, scope, filter, attrs){|entry|# print distinguished name
    
      p entry.dn
      # print all attribute names
      p entry.attrs
      # print values of attribute 'sn'
      p entry.vals('sn')# print entry as Hash
      p entry.to_hash
    }rescueLDAP::ResultError conn.perror("search") exit end conn.perror("search") conn.unbind

    This invokes the given code block for each matching entry where the LDAP entry is represented by an instance of the LDAP::Entry class. With the last parameter of search, you can specify the attributes in which you are interested, omitting all others. If you pass nil here, all attributes are returned same as “SELECT *” in relational databases.

    The dn method (alias for get_dn) of the LDAP::Entry class returns the distinguished name of the entry, and with the to_hash method, you can get a hash representation of its attributes (including the distinguished name). To get a list of an entry’s attributes, use the attrs method (alias for get_attributes). Also, to get the list of one specific attribute’s values, use the vals method (alias for get_values).

    Handling Errors

    Ruby/LDAP defines two different exception classes −

    • In case of an error, the new, bind or unbind methods raise an LDAP::Error exception.
    • In case of add, modify, delete or searching an LDAP directory raise an LDAP::ResultError.

    Further Reading

    For complete details on LDAP methods, please refer to the standard documentation for LDAP Documentation.

  • Tk Guide

    Introduction

    The standard graphical user interface (GUI) for Ruby is Tk. Tk started out as the GUI for the Tcl scripting language developed by John Ousterhout.

    Tk has the unique distinction of being the only cross-platform GUI. Tk runs on Windows, Mac, and Linux and provides a native look-and-feel on each operating system.

    The basic component of a Tk-based application is called a widget. A component is also sometimes called a window, since, in Tk, “window” and “widget” are often used interchangeably.

    Tk applications follow a widget hierarchy where any number of widgets may be placed within another widget, and those widgets within another widget, ad infinitum. The main widget in a Tk program is referred to as the root widget and can be created by making a new instance of the TkRoot class.

    • Most Tk-based applications follow the same cycle: create the widgets, place them in the interface, and finally, bind the events associated with each widget to a method.
    • There are three geometry managers; place, grid and pack that are responsible for controlling the size and location of each of the widgets in the interface.

    Installation

    The Ruby Tk bindings are distributed with Ruby but Tk is a separate installation. Windows users can download a single click Tk installation from ActiveState’s ActiveTcl.

    Mac and Linux users may not need to install it because there is a great chance that its already installed along with OS but if not, you can download prebuilt packages or get the source from the Tcl Developer Xchange.

    Simple Tk Application

    A typical structure for Ruby/Tk programs is to create the main or root window (an instance of TkRoot), add widgets to it to build up the user interface, and then start the main event loop by calling Tk.mainloop.

    The traditional Hello, World! example for Ruby/Tk looks something like this −

    require'tk'
    
    root =TkRoot.new{ title "Hello, World!"}TkLabel.new(root)do
       text 'Hello, World!'
       pack { padx 15; pady 15; side 'left'}endTk.mainloop
    

    Here, after loading the tk extension module, we create a root-level frame using TkRoot.new. We then make a TkLabel widget as a child of the root frame, setting several options for the label. Finally, we pack the root frame and enter the main GUI event loop.

    If you would run this script, it would produce the following result −

    Ruby/Tk Hello World

    Ruby/Tk Widget Classes

    There is a list of various Ruby/Tk classes, which can be used to create a desired GUI using Ruby/Tk.

    • TkFrame Creates and manipulates frame widgets.
    • TkButton Creates and manipulates button widgets.
    • TkLabel Creates and manipulates label widgets.
    • TkEntry Creates and manipulates entry widgets.
    • TkCheckButton Creates and manipulates checkbutton widgets.
    • TkRadioButton Creates and manipulates radiobutton widgets.
    • TkListbox Creates and manipulates listbox widgets.
    • TkComboBox Creates and manipulates listbox widgets.
    • TkMenu Creates and manipulates menu widgets.
    • TkMenubutton Creates and manipulates menubutton widgets.
    • Tk.messageBox Creates and manipulates a message dialog.
    • TkScrollbar Creates and manipulates scrollbar widgets.
    • TkCanvas Creates and manipulates canvas widgets.
    • TkScale Creates and manipulates scale widgets.
    • TkText Creates and manipulates text widgets.
    • TkToplevel Creates and manipulates toplevel widgets.
    • TkSpinbox Creates and manipulates Spinbox widgets.
    • TkProgressBar Creates and manipulates Progress Bar widgets.
    • Dialog Box Creates and manipulates Dialog Box widgets.
    • Tk::Tile::Notebook Display several windows in limited space with notebook metaphor.
    • Tk::Tile::Paned Displays a number of subwindows, stacked either vertically or horizontally.
    • Tk::Tile::Separator Displays a horizontal or vertical separator bar.
    • Ruby/Tk Font, Colors and Images Understanding Ruby/Tk Fonts, Colors and Images

    Standard Configuration Options

    All widgets have a number of different configuration options, which generally control how they are displayed or how they behave. The options that are available depend upon the widget class of course.

    Here is a list of all the standard configuration options, which could be applicable to any Ruby/Tk widget.There are other widget specific options also, which would be explained along with widgets.

    Ruby/Tk Geometry Management

    Geometry Management deals with positioning different widgets as per requirement. Geometry management in Tk relies on the concept of master and slave widgets.

    A master is a widget, typically a top-level window or a frame, which will contain other widgets, which are called slaves. You can think of a geometry manager as taking control of the master widget, and deciding what will be displayed within.

    The geometry manager will ask each slave widget for its natural size, or how large it would ideally like to be displayed. It then takes that information and combines it with any parameters provided by the program when it asks the geometry manager to manage that particular slave widget.

    There are three geometry managers place, grid and pack that are responsible for controlling the size and location of each of the widgets in the interface.

    • grid Geometry manager that arranges widgets in a grid.
    • pack Geometry manager that packs around edges of cavity.
    • place Geometry manager for fixed or rubber-sheet placement.

    Ruby/Tk Event Handling

    Ruby/Tk supports event loop, which receives events from the operating system. These are things like button presses, keystrokes, mouse movement, window resizing, and so on.

    Ruby/Tk takes care of managing this event loop for you. It will figure out what widget the event applies to (did the user click on this button? if a key was pressed, which textbox had the focus?), and dispatch it accordingly. Individual widgets know how to respond to events, so for example a button might change color when the mouse moves over it, and revert back when the mouse leaves.

    At a higher level, Ruby/Tk invokes callbacks in your program to indicate that something significant happened to a widget For either case, you can provide a code block or a Ruby Proc object that specifies how the application responds to the event or callback.

    Let’s take a look at how to use the bind method to associate basic window system events with the Ruby procedures that handle them. The simplest form of bind takes as its inputs a string indicating the event name and a code block that Tk uses to handle the event.

    For example, to catch the ButtonRelease event for the first mouse button on some widget, you’d write −

    someWidget.bind('ButtonRelease-1') {
       ....code block to handle this event...
    }
    

    An event name can include additional modifiers and details. A modifier is a string like ShiftControl or Alt, indicating that one of the modifier keys was pressed.

    So, for example, to catch the event that’s generated when the user holds down the Ctrl key and clicks the right mouse button.

    someWidget.bind('Control-ButtonPress-3', proc { puts "Ouch!"})

    Many Ruby/Tk widgets can trigger callbacks when the user activates them, and you can use the command callback to specify that a certain code block or procedure is invoked when that happens. As seen earlier, you can specify the command callback procedure when you create the widget −

    helpButton =TkButton.new(buttonFrame){
       text "Help"
       command proc { showHelp }}

    Or you can assign it later, using the widget’s command method −

    helpButton.command proc { showHelp }

    Since the command method accepts either procedures or code blocks, you could also write the previous code example as −

    helpButton =TkButton.new(buttonFrame){
       text "Help"
       command { showHelp }}

    You can use the following basic event types in your Ruby/Tk application −

    The configure Method

    The configure method can be used to set and retrieve any widget configuration values. For example, to change the width of a button you can call configure method any time as follows −

    require"tk"
    
    button =TkButton.new{
       text 'Hello World!'
       pack
    }
    button.configure('activebackground','blue')Tk.mainloop
    

    To get the value for a current widget, just supply it without a value as follows −

    color = button.configure('activebackground')

    You can also call configure without any options at all, which will give you a listing of all options and their values.

    The cget Method

    For simply retrieving the value of an option, configure returns more information than you generally want. The cget method returns just the current value.

  • Web Services with Ruby 

    What is SOAP?

    The Simple Object Access Protocol (SOAP), is a cross-platform and language-independent RPC protocol based on XML and, usually (but not necessarily) HTTP.

    It uses XML to encode the information that makes the remote procedure call, and HTTP to transport that information across a network from clients to servers and vice versa.

    SOAP has several advantages over other technologies like COM, CORBA etc: for example, its relatively cheap deployment and debugging costs, its extensibility and ease-of-use, and the existence of several implementations for different languages and platforms.

    Please refer to our simple tutorial SOAP to understand it in detail.

    This chapter makes you familiar with the SOAP implementation for Ruby (SOAP4R). This is a basic tutorial, so if you need a deep detail, you would need to refer other resources.

    Installing SOAP4R

    SOAP4R is the SOAP implementation for Ruby developed by Hiroshi Nakamura and can be downloaded from −

    NOTE − There may be a great chance that you already have installed this component.

    Download SOAP

    If you are aware of gem utility then you can use the following command to install SOAP4R and related packages.

    $ gem install soap4r --include-dependencies
    

    If you are working on Windows, then you need to download a zipped file from the above location and need to install it using the standard installation method by running ruby install.rb.

    Writing SOAP4R Servers

    SOAP4R supports two different types of servers −

    • CGI/FastCGI based (SOAP::RPC::CGIStub)
    • Standalone (SOAP::RPC:StandaloneServer)

    This chapter gives detail on writing a stand alone server. The following steps are involved in writing a SOAP server.

    Step 1 – Inherit SOAP::RPC::StandaloneServer Class

    To implement your own stand alone server you need to write a new class, which will be child of SOAP::StandaloneServer as follows −

    classMyServer<SOAP::RPC::StandaloneServer...............end

    NOTE − If you want to write a FastCGI based server then you need to take SOAP::RPC::CGIStub as parent class, rest of the procedure will remain the same.

    Step 2 – Define Handler Methods

    Second step is to write your Web Services methods, which you would like to expose to the outside world.

    They can be written as simple Ruby methods. For example, let’s write two methods to add two numbers and divide two numbers −

    classMyServer<SOAP::RPC::StandaloneServer...............# Handler methodsdefadd(a, b)return a &plus; b
       enddefdiv(a, b)return a / b 
       endend

    Step 3 – Expose Handler Methods

    Next step is to add our defined methods to our server. The initialize method is used to expose service methods with one of the two following methods −

    classMyServer<SOAP::RPC::StandaloneServerdefinitialize(*args)
    
      add_method(receiver, methodName,*paramArg)endend</pre>

    Here is the description of the parameters −

    Sr.No.Parameter & Description
    1receiverThe object that contains the methodName method. You define the service methods in the same class as the methodDef method, this parameter is self.
    2methodNameThe name of the method that is called due to an RPC request.
    3paramArgSpecifies, when given, the parameter names and parameter modes.

    To understand the usage of inout or out parameters, consider the following service method that takes two parameters (inParam and inoutParam), returns one normal return value (retVal) and two further parameters: inoutParam and outParam −

    defaMeth(inParam, inoutParam)
       retVal = inParam &plus; inoutParam
       outParam = inParam . inoutParam
       inoutParam = inParam * inoutParam
       return retVal, inoutParam, outParam
    end

    Now, we can expose this method as follows −

    add_method(self,'aMeth',[%w(in inParam),%w(inout inoutParam),%w(out outParam),%w(retval return)])

    Step 4 - Start the Server

    The final step is to start your server by instantiating one instance of the derived class and calling start method.

    myServer =MyServer.new('ServerName','urn:ruby:ServiceName', hostname, port)
    
    myServer.start
    

    Here is the description of required parameters −

    Sr.No.Parameter & Description
    1ServerNameA server name, you can give what you like most.
    2urn:ruby:ServiceNameHere urn:ruby is constant but you can give a unique ServiceName name for this server.
    3hostnameSpecifies the hostname on which this server will listen.
    4portAn available port number to be used for the web service.

    Example

    Now, using the above steps, let us write one standalone server −

    require"soap/rpc/standaloneserver"beginclassMyServer<SOAP::RPC::StandaloneServer# Expose our servicesdefinitialize(*args)
    
         add_method(self,'add','a','b')
         add_method(self,'div','a','b')end# Handler methodsdefadd(a, b)return a &amp;plus; b
      enddefdiv(a, b)return a / b 
      endend
    server =MyServer.new("MyServer",'urn:ruby:calculation','localhost',8080) trap('INT){
      server.shutdown
    } server.start rescue=> err puts err.message end

    When executed, this server application starts a standalone SOAP server on localhost and listens for requests on port 8080. It exposes one service methods, add and div, which takes two parameters and return the result.

    Now, you can run this server in background as follows −

    $ ruby MyServer.rb&
    

    Writing SOAP4R Clients

    The SOAP::RPC::Driver class provides support for writing SOAP client applications. This chapter describes this class and demonstrate its usage on the basis of an application.

    Following is the bare minimum information you would need to call a SOAP service −

    • The URL of the SOAP service (SOAP Endpoint URL).
    • The namespace of the service methods (Method Namespace URI).
    • The names of the service methods and their parameters.

    Now, we will write a SOAP client which would call service methods defined in above example, named add and div.

    Here are the main steps to create a SOAP client.

    Step 1 - Create a SOAP Driver Instance

    We create an instance of SOAP::RPC::Driver by calling its new method as follows −

    SOAP::RPC::Driver.new(endPoint, nameSpace, soapAction)

    Here is the description of required parameters −

    Sr.No.Parameter & Description
    1endPointURL of the SOAP server to connect with.
    2nameSpaceThe namespace to use for all RPCs done with this SOAP::RPC::Driver object.
    3soapActionA value for the SOAPAction field of the HTTP header. If nil this defaults to the empty string "".

    Step 2 - Add Service Methods

    To add a SOAP service method to a SOAP::RPC::Driver we can call the following method using SOAP::RPC::Driver instance −

    driver.add_method(name,*paramArg)

    Here is the description of the parameters −

    Sr.No.Parameter & Description
    1nameThe name of the remote web service method.
    2paramArgSpecifies the names of the remote procedures' parameters.

    Step 3 - Invoke SOAP service

    The final step is to invoice SOAP service using SOAP::RPC::Driver instance as follows −

    result = driver.serviceMethod(paramArg...)

    Here serviceMethod is the actual web service method and paramArg... is the list parameters required to pass in the service method.

    Example

    Based on the above steps, we will write a SOAP client as follows −

    #!/usr/bin/ruby -wrequire'soap/rpc/driver'NAMESPACE='urn:ruby:calculation'URL='http://localhost:8080/'begin
       driver =SOAP::RPC::Driver.new(URL,NAMESPACE)# Add remote sevice methods
       driver.add_method('add','a','b')# Call remote service methods
       puts driver.add(20,30)rescue=> err
       puts err.message
    end

    Further Readings

    I have explained you just very basic concepts of Web Services with Ruby. If you want to drill down it further.

  • XML, XSLT

    What is XML?

    The Extensible Markup Language (XML) is a markup language much like HTML or SGML. This is recommended by the World Wide Web Consortium and available as an open standard.

    XML is a portable, open source language that allows programmers to develop applications that can be read by other applications, regardless of operating system and/or developmental language.

    XML is extremely useful for keeping track of small to medium amounts of data without requiring a SQL-based backbone.

    XML Parser Architectures and APIs

    There are two different flavors available for XML parsers −

    • SAX-like (Stream interfaces) − Here you register callbacks for events of interest and then let the parser proceed through the document. This is useful when your documents are large or you have memory limitations, it parses the file as it reads it from disk, and the entire file is never stored in memory.
    • DOM-like (Object tree interfaces) − This is World Wide Web Consortium recommendation wherein the entire file is read into memory and stored in a hierarchical (tree-based) form to represent all the features of an XML document.

    SAX obviously can’t process information as fast as DOM can when working with large files. On the other hand, using DOM exclusively can really kill your resources, especially if used on a lot of small files.

    SAX is read-only, while DOM allows changes to the XML file. Since these two different APIs literally complement each other there is no reason why you can’t use them both for large projects.

    Parsing and Creating XML using Ruby

    The most common way to manipulate XML is with the REXML library by Sean Russell. Since 2002, REXML has been part of the standard Ruby distribution.

    REXML is a pure-Ruby XML processor conforming to the XML 1.0 standard. It is a non-validating processor, passing all of the OASIS non-validating conformance tests.

    REXML parser has the following advantages over other available parsers −

    • It is written 100 percent in Ruby.
    • It can be used for both SAX and DOM parsing.
    • It is lightweight, less than 2000 lines of code.
    • Methods and classes are really easy-to-understand.
    • SAX2-based API and Full XPath support.
    • Shipped with Ruby installation and no separate installation is required.

    For all our XML code examples, let’s use a simple XML file as an input −

    <collection shelf = "New Arrivals">
       <movie title = "Enemy Behind">
    
      &lt;type&gt;War, Thriller&lt;/type&gt;
      &lt;format&gt;DVD&lt;/format&gt;
      &lt;year&gt;2003&lt;/year&gt;
      &lt;rating&gt;PG&lt;/rating&gt;
      &lt;stars&gt;10&lt;/stars&gt;
      &lt;description&gt;Talk about a US-Japan war&lt;/description&gt;
    </movie> <movie title = "Transformers">
      &lt;type&gt;Anime, Science Fiction&lt;/type&gt;
      &lt;format&gt;DVD&lt;/format&gt;
      &lt;year&gt;1989&lt;/year&gt;
      &lt;rating&gt;R&lt;/rating&gt;
      &lt;stars&gt;8&lt;/stars&gt;
      &lt;description&gt;A schientific fiction&lt;/description&gt;
    </movie> <movie title = "Trigun">
      &lt;type&gt;Anime, Action&lt;/type&gt;
      &lt;format&gt;DVD&lt;/format&gt;
      &lt;episodes&gt;4&lt;/episodes&gt;
      &lt;rating&gt;PG&lt;/rating&gt;
      &lt;stars&gt;10&lt;/stars&gt;
      &lt;description&gt;Vash the Stampede!&lt;/description&gt;
    </movie> <movie title = "Ishtar">
      &lt;type&gt;Comedy&lt;/type&gt;
      &lt;format&gt;VHS&lt;/format&gt;
      &lt;rating&gt;PG&lt;/rating&gt;
      &lt;stars&gt;2&lt;/stars&gt;
      &lt;description&gt;Viewable boredom&lt;/description&gt;
    </movie> </collection>

    DOM-like Parsing

    Let’s first parse our XML data in tree fashion. We begin by requiring the rexml/document library; often we do an include REXML to import into the top-level namespace for convenience.

    #!/usr/bin/ruby -w
    
    require 'rexml/document'
    include REXML
    
    xmlfile = File.new("movies.xml")
    xmldoc = Document.new(xmlfile)
    
    # Now get the root element
    root = xmldoc.root
    puts "Root element : " + root.attributes["shelf"]
    
    # This will output all the movie titles.
    xmldoc.elements.each("collection/movie"){ 
       |e| puts "Movie Title : " + e.attributes["title"] 
    }
    
    # This will output all the movie types.
    xmldoc.elements.each("collection/movie/type") {
       |e| puts "Movie Type : " + e.text 
    }
    
    # This will output all the movie description.
    xmldoc.elements.each("collection/movie/description") {
       |e| puts "Movie Description : " + e.text 
    }
    

    This will produce the following result −

    Root element : New Arrivals
    Movie Title : Enemy Behind
    Movie Title : Transformers
    Movie Title : Trigun
    Movie Title : Ishtar
    Movie Type : War, Thriller
    Movie Type : Anime, Science Fiction
    Movie Type : Anime, Action
    Movie Type : Comedy
    Movie Description : Talk about a US-Japan war
    Movie Description : A schientific fiction
    Movie Description : Vash the Stampede!
    Movie Description : Viewable boredom
    

    SAX-like Parsing

    To process the same data, movies.xml, file in a stream-oriented way we will define a listener class whose methods will be the target of callbacks from the parser.

    NOTE − It is not suggested to use SAX-like parsing for a small file, this is just for a demo example.

    #!/usr/bin/ruby -w
    
    require 'rexml/document'
    require 'rexml/streamlistener'
    include REXML
    
    class MyListener
       include REXML::StreamListener
       def tag_start(*args)
    
      puts "tag_start: #{args.map {|x| x.inspect}.join(', ')}"
    end def text(data)
      return if data =~ /^\w*$/     # whitespace only
      abbrev = data[0..40] + (data.length &gt; 40 ? "..." : "")
      puts "  text   :   #{abbrev.inspect}"
    end end list = MyListener.new xmlfile = File.new("movies.xml") Document.parse_stream(xmlfile, list)

    This will produce the following result −

    tag_start: "collection", {"shelf"=>"New Arrivals"}
    tag_start: "movie", {"title"=>"Enemy Behind"}
    tag_start: "type", {}
       text   :   "War, Thriller"
    tag_start: "format", {}
    tag_start: "year", {}
    tag_start: "rating", {}
    tag_start: "stars", {}
    tag_start: "description", {}
       text   :   "Talk about a US-Japan war"
    tag_start: "movie", {"title"=>"Transformers"}
    tag_start: "type", {}
       text   :   "Anime, Science Fiction"
    tag_start: "format", {}
    tag_start: "year", {}
    tag_start: "rating", {}
    tag_start: "stars", {}
    tag_start: "description", {}
       text   :   "A schientific fiction"
    tag_start: "movie", {"title"=>"Trigun"}
    tag_start: "type", {}
       text   :   "Anime, Action"
    tag_start: "format", {}
    tag_start: "episodes", {}
    tag_start: "rating", {}
    tag_start: "stars", {}
    tag_start: "description", {}
       text   :   "Vash the Stampede!"
    tag_start: "movie", {"title"=>"Ishtar"}
    tag_start: "type", {}
    tag_start: "format", {}
    tag_start: "rating", {}
    tag_start: "stars", {}
    tag_start: "description", {}
       text   :   "Viewable boredom"
    

    XPath and Ruby

    An alternative way to view XML is XPath. This is a kind of pseudo-language that describes how to locate specific elements and attributes in an XML document, treating that document as a logical ordered tree.

    REXML has XPath support via the XPath class. It assumes tree-based parsing (document object model) as we have seen above.

    #!/usr/bin/ruby -w
    
    require 'rexml/document'
    include REXML
    
    xmlfile = File.new("movies.xml")
    xmldoc = Document.new(xmlfile)
    
    # Info for the first movie found
    movie = XPath.first(xmldoc, "//movie")
    p movie
    
    # Print out all the movie types
    XPath.each(xmldoc, "//type") { |e| puts e.text }
    
    # Get an array of all of the movie formats.
    names = XPath.match(xmldoc, "//format").map {|x| x.text }
    p names
    

    This will produce the following result −

    <movie title = 'Enemy Behind'> ... </>
    War, Thriller
    Anime, Science Fiction
    Anime, Action
    Comedy
    ["DVD", "DVD", "DVD", "VHS"]
    

    XSLT and Ruby

    There are two XSLT parsers available that Ruby can use. A brief description of each is given here.

    Ruby-Sablotron

    This parser is written and maintained by Masayoshi Takahashi. This is written primarily for Linux OS and requires the following libraries −

    • Sablot
    • Iconv
    • Expat

    You can find this module at Ruby-Sablotron.

    XSLT4R

    XSLT4R is written by Michael Neumann and can be found at the RAA in the Library section under XML. XSLT4R uses a simple commandline interface, though it can alternatively be used within a third-party application to transform an XML document.

    XSLT4R needs XMLScan to operate, which is included within the XSLT4R archive and which is also a 100 percent Ruby module. These modules can be installed using standard Ruby installation method (i.e., ruby install.rb).

    XSLT4R has the following syntax −

    ruby xslt.rb stylesheet.xsl document.xml [arguments]
    

    If you want to use XSLT4R from within an application, you can include XSLT and input the parameters you need. Here is the example −

    require"xslt"
    
    stylesheet =File.readlines("stylesheet.xsl").to_s
    xml_doc =File.readlines("document.xml").to_s
    arguments ={'image_dir'=>'/....'}
    sheet =XSLT::Stylesheet.new( stylesheet, arguments )# output to StdOut
    sheet.apply( xml_doc )# output to 'str'
    str =""
    sheet.output =[ str ]
    sheet.apply( xml_doc )

    Further Reading

  • Socket Programming

    Ruby provides two levels of access to network services. At a low level, you can access the basic socket support in the underlying operating system, which allows you to implement clients and servers for both connection-oriented and connectionless protocols.

    Ruby also has libraries that provide higher-level access to specific application-level network protocols, such as FTP, HTTP, and so on.

    This chapter gives you an understanding on most famous concept in Networking − Socket Programming.

    What are Sockets?

    Sockets are the endpoints of a bidirectional communications channel. Sockets may communicate within a process, between processes on the same machine, or between processes on different continents.

    Sockets may be implemented over a number of different channel types: Unix domain sockets, TCP, UDP, and so on. The socket provides specific classes for handling the common transports as well as a generic interface for handling the rest.

    Sockets have their own vocabulary −

    Sr.No.Term & Description
    1domainThe family of protocols that will be used as the transport mechanism. These values are constants such as PF_INET, PF_UNIX, PF_X25, and so on.
    2typeThe type of communications between the two endpoints, typically SOCK_STREAM for connection-oriented protocols and SOCK_DGRAM for connectionless protocols.
    3protocolTypically zero, this may be used to identify a variant of a protocol within a domain and type.
    4hostnameThe identifier of a network interface −A string, which can be a host name, a dotted-quad address, or an IPV6 address in colon (and possibly dot) notationA string “<broadcast>”, which specifies an INADDR_BROADCAST address.A zero-length string, which specifies INADDR_ANY, orAn Integer, interpreted as a binary address in host byte order.
    5portEach server listens for clients calling on one or more ports. A port may be a Fixnum port number, a string containing a port number, or the name of a service.

    A Simple Client

    Here we will write a very simple client program, which will open a connection to a given port and given host. Ruby class TCPSocket provides open function to open such a socket.

    The TCPSocket.open(hosname, port ) opens a TCP connection to hostname on the port.

    Once you have a socket open, you can read from it like any IO object. When done, remember to close it, as you would close a file.

    The following code is a very simple client that connects to a given host and port, reads any available data from the socket, and then exits −

    require'socket'# Sockets are in standard library
    
    hostname ='localhost'
    port =2000
    
    s =TCPSocket.open(hostname, port)while line = s.gets     # Read lines from the socket
       puts line.chop       # And print with platform line terminatorend
    s.close                 # Close the socket when done

    A Simple Server

    To write Internet servers, we use the TCPServer class. A TCPServer object is a factory for TCPSocket objects.

    Now call TCPServer.open(hostname, port function to specify a port for your service and create a TCPServer object.

    Next, call the accept method of the returned TCPServer object. This method waits until a client connects to the port you specified, and then returns a TCPSocket object that represents the connection to that client.

    require'socket'# Get sockets from stdlib
    
    server =TCPServer.open(2000)# Socket to listen on port 2000
    loop {# Servers run forever
       client = server.accept        # Wait for a client to connect
       client.puts(Time.now.ctime)# Send the time to the client
       client.puts "Closing the connection. Bye!"
       client.close                  # Disconnect from the client}

    Now, run this server in background and then run the above client to see the result.

    Multi-Client TCP Servers

    Most servers on the Internet are designed to deal with large numbers of clients at any one time.

    Ruby’s Thread class makes it easy to create a multithreaded server.one that accepts requests and immediately creates a new thread of execution to process the connection while allowing the main program to await more connections −

    require'socket'# Get sockets from stdlib
    
    server =TCPServer.open(2000)# Socket to listen on port 2000
    loop {# Servers run foreverThread.start(server.accept)do|client|
       client.puts(Time.now.ctime)# Send the time to the client
       client.puts "Closing the connection. Bye!"
       client.close                  # Disconnect from the clientend}

    In this example, you have a permanent loop, and when server.accept responds, a new thread is created and started immediately to handle the connection that has just been accepted, using the connection object passed into the thread. However, the main program immediately loops back and awaits new connections.

    Using Ruby threads in this way means the code is portable and will run in the same way on Linux, OS X, and Windows.

    A Tiny Web Browser

    We can use the socket library to implement any Internet protocol. Here, for example, is a code to fetch the content of a web page −

    require'socket'
     
    host ='www.tutorialspoint.com'# The web server
    port =80# Default HTTP port
    path ="/index.htm"# The file we want # This is the HTTP request we send to fetch a file
    request ="GET #{path} HTTP/1.0\r\n\r\n"
    
    socket =TCPSocket.open(host,port)# Connect to server
    socket.print(request)# Send request
    response = socket.read              # Read complete response# Split response at first blank line into headers and body
    headers,body = response.split("\r\n\r\n",2) 
    print body                          # And display it

    To implement the similar web client, you can use a pre-built library like Net::HTTP for working with HTTP. Here is the code that does the equivalent of the previous code −

    require'net/http'# The library we need
    host ='www.tutorialspoint.com'# The web server
    path ='/index.htm'# The file we want 
    
    http =Net::HTTP.new(host)# Create a connection
    headers, body = http.get(path)# Request the fileif headers.code =="200"# Check the status code   
       print body                        
    else                                
       puts "#{headers.code} #{headers.message}"end

    Please check similar libraries to work with FTP, SMTP, POP, and IMAP protocols.

    Further Readings

    We have given you a quick start on Socket Programming. It is a big subject, so it is recommended that you go through Ruby Socket Library and Class Methods to find more details.