Author: Saim Khalid

  • CGI Programming

    Ruby is a general-purpose language; it can’t properly be called a web language at all. Even so, web applications and web tools in general are among the most common uses of Ruby.

    Not only can you write your own SMTP server, FTP daemon, or Web server in Ruby, but you can also use Ruby for more usual tasks such as CGI programming or as a replacement for PHP.

    Please spend few minutes with CGI Programming Tutorial for more detail on CGI Programming.

    Writing CGI Scripts

    The most basic Ruby CGI script looks like this −

    #!/usr/bin/ruby
    
    puts "HTTP/1.0 200 OK"
    puts "Content-type: text/html\n\n"
    puts "<html><body>This is a test</body></html>"

    If you call this script test.cgi and uploaded it to a Unix-based Web hosting provider with the right permissions, you could use it as a CGI script.

    For example, if you have the Web site https://www.example.com/ hosted with a Linux Web hosting provider and you upload test.cgi to the main directory and give it execute permissions, then visiting https://www.example.com/test.cgi should return an HTML page saying This is a test.

    Here when test.cgi is requested from a Web browser, the Web server looks for test.cgi on the Web site, and then executes it using the Ruby interpreter. The Ruby script returns a basic HTTP header and then returns a basic HTML document.

    Using cgi.rb

    Ruby comes with a special library called cgi that enables more sophisticated interactions than those with the preceding CGI script.

    Let’s create a basic CGI script that uses cgi −

    #!/usr/bin/rubyrequire'cgi'
    cgi =CGI.new
    
    puts cgi.header
    puts "<html><body>This is a test</body></html>"

    Here, you created a CGI object and used it to print the header line for you.

    Form Processing

    Using class CGI gives you access to HTML query parameters in two ways. Suppose we are given a URL of /cgi-bin/test.cgi?FirstName = Zara&LastName = Ali.

    You can access the parameters FirstName and LastName using CGI#[] directly as follows −

    #!/usr/bin/rubyrequire'cgi'
    cgi =CGI.new
    cgi['FirstName']# =>  ["Zara"]
    cgi['LastName']# =>  ["Ali"]

    There is another way to access these form variables. This code will give you a hash of all the key and values −

    #!/usr/bin/rubyrequire'cgi'
    cgi =CGI.new
    h = cgi.params  # =>  {"FirstName"=>["Zara"],"LastName"=>["Ali"]}
    h['FirstName']# =>  ["Zara"]
    h['LastName']# =>  ["Ali"]

    Following is the code to retrieve all the keys −

    #!/usr/bin/rubyrequire'cgi'
    cgi =CGI.new
    cgi.keys         # =>  ["FirstName", "LastName"]

    If a form contains multiple fields with the same name, the corresponding values will be returned to the script as an array. The [] accessor returns just the first of these.index the result of the params method to get them all.

    In this example, assume the form has three fields called “name” and we entered three names “Zara”, “Huma” and “Nuha” −

    #!/usr/bin/rubyrequire'cgi'
    cgi =CGI.new
    cgi['name']# => "Zara"
    cgi.params['name']# => ["Zara", "Huma", "Nuha"]
    cgi.keys           # => ["name"]
    cgi.params         # => {"name"=>["Zara", "Huma", "Nuha"]}

    Note − Ruby will take care of GET and POST methods automatically. There is no separate treatment for these two different methods.

    An associated, but basic, form that could send the correct data would have the HTML code like so −

    <html><body><form method ="POST" action ="http://www.example.com/test.cgi">FirstName:<input type ="text" name ="FirstName" value =""/><br />LastName:<input type ="text" name ="LastName" value =""/><input type ="submit" value ="Submit Data"/></form></body></html>

    Creating Forms and HTML

    CGI contains a huge number of methods used to create HTML. You will find one method per tag. In order to enable these methods, you must create a CGI object by calling CGI.new.

    To make tag nesting easier, these methods take their content as code blocks. The code blocks should return a String, which will be used as the content for the tag. For example −

    #!/usr/bin/rubyrequire"cgi"
    cgi =CGI.new("html4")
    cgi.out {
       cgi.html {
    
      cgi.head {"\n"&amp;plus;cgi.title{"This Is a Test"}}&amp;plus;
      cgi.body {"\n"&amp;plus;
         cgi.form {"\n"&amp;plus;
            cgi.hr &amp;plus;
            cgi.h1 {"A Form: "}&amp;plus;"\n"&amp;plus;
            cgi.textarea("get_text")&amp;plus;"\n"+
            cgi.br +
            cgi.submit
         }}}}</pre>

    NOTE − The form method of the CGI class can accept a method parameter, which will set the HTTP method ( GET, POST, and so on...) to be used on form submittal. The default, used in this example, is POST.

    This will produce the following result −

    Content-Type: text/html
    Content-Length: 302
    
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Final//EN">
    
    <HTML>
       <HEAD>
    
      &lt;TITLE&gt;This Is a Test&lt;/TITLE&gt;
    </HEAD> <BODY>
      &lt;FORM METHOD = "post" ENCTYPE = "application/x-www-form-urlencoded"&gt;
         &lt;HR&gt;
         &lt;H1&gt;A Form: &lt;/H1&gt;
         &lt;TEXTAREA COLS = "70" NAME = "get_text" ROWS = "10"&gt;&lt;/TEXTAREA&gt;
         &lt;BR&gt;
         &lt;INPUT TYPE = "submit"&gt;
      &lt;/FORM&gt;
    </BODY> </HTML>

    Quoting Strings

    When dealing with URLs and HTML code, you must be careful to quote certain characters. For instance, a slash character ( / ) has special meaning in a URL, so it must be escaped if it's not part of the pathname.

    For example, any / in the query portion of the URL will be translated to the string %2F and must be translated back to a / for you to use it. Space and ampersand are also special characters. To handle this, CGI provides the routines CGI.escape and CGI.unescape.

    #!/usr/bin/rubyrequire'cgi'
    puts CGI.escape(ZaraAli/ASweet&SourGirl")

    This will produce the following result −

    Zara+Ali%2FA Sweet+%26+Sour+Girl")
    
    #!/usr/bin/rubyrequire'cgi'
    puts CGI.escapeHTML('<h1>Zara Ali/A Sweet & Sour Girl</h1>')

    This will produce the following result −

    &lt;h1&gt;Zara Ali/A Sweet & Sour Girl&lt;/h1&gt;'
    

    Useful Methods in CGI Class

    Here is the list of methods related to CGI class −

    • The Ruby CGI − Methods related to Standard CGI library.

    Cookies and Sessions

    We have explained these two concepts in different sections. Please follow the sections −

    • The Ruby CGI Cookies − How to handle CGI Cookies.
    • The Ruby CGI Sessions − How to manage CGI sessions.

    Web Hosting Servers

    You could check the following topic on the internet to host your website on a Unix-based Server −

    • Unix-based Web hosting
  • Database Access

    This chapter teaches you how to access a database using Ruby. The Ruby DBI module provides a database-independent interface for Ruby scripts similar to that of the Perl DBI module.

    DBI stands for Database Independent Interface for Ruby, which means DBI provides an abstraction layer between the Ruby code and the underlying database, allowing you to switch database implementations really easily. It defines a set of methods, variables, and conventions that provide a consistent database interface, independent of the actual database being used.

    DBI can interface with the following −

    • ADO (ActiveX Data Objects)
    • DB2
    • Frontbase
    • mSQL
    • MySQL
    • ODBC
    • Oracle
    • OCI8 (Oracle)
    • PostgreSQL
    • Proxy/Server
    • SQLite
    • SQLRelay

    Architecture of a DBI Application

    DBI is independent of any database available in the backend. You can use DBI whether you are working with Oracle, MySQL or Informix, etc. This is clear from the following architecture diagram.

    Ruby DBI Architecture

    The general architecture for Ruby DBI uses two layers −

    • The database interface (DBI) layer. This layer is database independent and provides a set of common access methods that are used the same way regardless of the type of database server with which you’re communicating.
    • The database driver (DBD) layer. This layer is database dependent; different drivers provide access to different database engines. There is one driver for MySQL, another for PostgreSQL, another for InterBase, another for Oracle, and so forth. Each driver interprets requests from the DBI layer and maps them onto requests appropriate for a given type of database server.

    Prerequisites

    If you want to write Ruby scripts to access MySQL databases, you’ll need to have the Ruby MySQL module installed.

    This module acts as a DBD as explained above and can be downloaded from https://www.tmtm.org/en/mysql/ruby/

    Obtaining and Installing Ruby/DBI

    You can install ruby DBI using the Ruby Gems packaging manager:

    gem install dbi
    

    Before starting this installation make sure you have the root privilege. Now, follow the steps given below −

    Step 1

    $ tar zxf dbi-0.2.0.tar.gz
    

    Step 2

    Go in distribution directory dbi-0.2.0 nd configure it using the setup.rb script in that directory. The most general configuration command looks like this, with no arguments following the config argument. This command configures the distribution to install all drivers by default.

    $ ruby setup.rb config
    

    To be more specific, provide a –with option that lists the particular parts of the distribution you want to use. For example, to configure only the main DBI module and the MySQL DBD-level driver, issue the following command −

    $ ruby setup.rb config --with = dbi,dbd_mysql
    

    Step 3

    Final step is to build the driver and install it using the following commands −

    $ ruby setup.rb setup
    $ ruby setup.rb install
    

    Database Connection

    Assuming we are going to work with MySQL database, before connecting to a database make sure of the following −

    • You have created a database TESTDB.
    • You have created EMPLOYEE in TESTDB.
    • This table is having fields FIRST_NAME, LAST_NAME, AGE, SEX, and INCOME.
    • User ID “testuser” and password “test123” are set to access TESTDB.
    • Ruby Module DBI is installed properly on your machine.
    • You have gone through MySQL tutorial to understand MySQL Basics.

    Following is the example of connecting with MySQL database “TESTDB”

    #!/usr/bin/ruby -wrequire"dbi"begin# connect to the MySQL server
       dbh =DBI.connect("DBI:Mysql:TESTDB:localhost","testuser","test123")# get server version string and display it
       row = dbh.select_one("SELECT VERSION()")
       puts "Server version: "+ row[0]rescueDBI::DatabaseError=> e
       puts "An error occurred"
       puts "Error code:    #{e.err}"
       puts "Error message: #{e.errstr}"ensure# disconnect from server
       dbh.disconnect if dbh
    end

    While running this script, it produces the following result at our Linux machine.

    Server version: 5.0.45
    

    If a connection is established with the data source, then a Database Handle is returned and saved into dbh for further use otherwise dbh is set to nil value and e.err and e::errstr return error code and an error string respectively.

    Finally, before coming out it, ensure that database connection is closed and resources are released.

    INSERT Operation

    INSERT operation is required when you want to create your records into a database table.

    Once a database connection is established, we are ready to create tables or records into the database tables using do method or prepare and execute method.

    Using do Statement

    Statements that do not return rows can be issued by invoking the do database handle method. This method takes a statement string argument and returns a count of the number of rows affected by the statement.

    dbh.do("DROP TABLE IF EXISTS EMPLOYEE")
    dbh.do("CREATETABLEEMPLOYEE(FIRST_NAMECHAR(20)NOTNULL,LAST_NAMECHAR(20),AGEINT,SEXCHAR(1),INCOMEFLOAT)" );

    Similarly, you can execute the SQL INSERT statement to create a record into the EMPLOYEE table.

    #!/usr/bin/ruby -wrequire"dbi"begin# connect to the MySQL server
       dbh =DBI.connect("DBI:Mysql:TESTDB:localhost","testuser","test123")
       dbh.do( "INSERTINTOEMPLOYEE(FIRST_NAME,LAST_NAME,AGE,SEX,INCOME)VALUES('Mac','Mohan',20,'M',2000)" )
       puts "Record has been created"
       dbh.commit
    rescueDBI::DatabaseError=> e
       puts "An error occurred"
       puts "Error code:    #{e.err}"
       puts "Error message: #{e.errstr}"
       dbh.rollback
    ensure# disconnect from server
       dbh.disconnect if dbh
    end

    Using prepare and execute

    You can use prepare and execute methods of DBI class to execute the SQL statement through Ruby code.

    Record creation takes the following steps −

    • Preparing SQL statement with INSERT statement. This will be done using the prepare method.
    • Executing SQL query to select all the results from the database. This will be done using the execute method.
    • Releasing Statement handle. This will be done using finish API
    • If everything goes fine, then commit this operation otherwise you can rollback the complete transaction.

    Following is the syntax to use these two methods −

    sth = dbh.prepare(statement)
    sth.execute
       ... zero or more SQL operations ...
    sth.finish
    

    These two methods can be used to pass bind values to SQL statements. There may be a case when values to be entered is not given in advance. In such a case, binding values are used. A question mark (?) is used in place of actual values and then actual values are passed through execute() API.

    Following is the example to create two records in the EMPLOYEE table −

    #!/usr/bin/ruby -wrequire"dbi"begin# connect to the MySQL server
       dbh =DBI.connect("DBI:Mysql:TESTDB:localhost","testuser","test123")
       sth = dbh.prepare( "INSERTINTOEMPLOYEE(FIRST_NAME,LAST_NAME,AGE,SEX,INCOME)VALUES(?,?,?,?,?)" )
       sth.execute('John','Poul',25,'M',2300)
       sth.execute('Zara','Ali',17,'F',1000)
       sth.finish
       dbh.commit
       puts "Record has been created"rescueDBI::DatabaseError=> e
       puts "An error occurred"
       puts "Error code:    #{e.err}"
       puts "Error message: #{e.errstr}"
       dbh.rollback
    ensure# disconnect from server
       dbh.disconnect if dbh
    end

    If there are multiple INSERTs at a time, then preparing a statement first and then executing it multiple times within a loop is more efficient than invoking do each time through the loop.

    READ Operation

    READ Operation on any database means to fetch some useful information from the database.

    Once our database connection is established, we are ready to make a query into this database. We can use either do method or prepare and execute methods to fetch values from a database table.

    Record fetching takes following steps −

    • Preparing SQL query based on required conditions. This will be done using the prepare method.
    • Executing SQL query to select all the results from the database. This will be done using the execute method.
    • Fetching all the results one by one and printing those results. This will be done using the fetch method.
    • Releasing Statement handle. This will be done using the finish method.

    Following is the procedure to query all the records from EMPLOYEE table having salary more than 1000.

    #!/usr/bin/ruby -wrequire"dbi"begin# connect to the MySQL server
       dbh =DBI.connect("DBI:Mysql:TESTDB:localhost","testuser","test123")
       sth = dbh.prepare("SELECT * FROM EMPLOYEE WHERE INCOME > ?")
       sth.execute(1000)
    
       sth.fetch do|row|
       printf "First Name: %s, Last Name : %s\n", row[0], row[1]
       printf "Age: %d, Sex : %s\n", row[2], row[3]
       printf "Salary :%d \n\n", row[4]end
       sth.finish
    rescueDBI::DatabaseError=> e
       puts "An error occurred"
       puts "Error code:    #{e.err}"
       puts "Error message: #{e.errstr}"ensure# disconnect from server
       dbh.disconnect if dbh
    end

    This will produce the following result −

    First Name: Mac, Last Name : Mohan
    Age: 20, Sex : M
    Salary :2000
    
    First Name: John, Last Name : Poul
    Age: 25, Sex : M
    Salary :2300
    

    There are more short cut methods to fetch records from the database. If you are interested then go through the Fetching the Result otherwise proceed to the next section.

    Update Operation

    UPDATE Operation on any database means to update one or more records, which are already available in the database. Following is the procedure to update all the records having SEX as ‘M’. Here, we will increase AGE of all the males by one year. This will take three steps −

    • Preparing SQL query based on required conditions. This will be done using the prepare method.
    • Executing SQL query to select all the results from the database. This will be done using the execute method.
    • Releasing Statement handle. This will be done using the finish method.
    • If everything goes fine then commit this operation otherwise you can rollback the complete transaction.
    #!/usr/bin/ruby -wrequire"dbi"begin# connect to the MySQL server
       dbh =DBI.connect("DBI:Mysql:TESTDB:localhost","testuser","test123")
       sth = dbh.prepare("UPDATE EMPLOYEE SET AGE = AGE + 1 WHERE SEX = ?")
       sth.execute('M')
       sth.finish
       dbh.commit
    rescueDBI::DatabaseError=> e
       puts "An error occurred"
       puts "Error code:    #{e.err}"
       puts "Error message: #{e.errstr}"
       dbh.rollback
    ensure# disconnect from server
       dbh.disconnect if dbh
    end

    DELETE Operation

    DELETE operation is required when you want to delete some records from your database. Following is the procedure to delete all the records from EMPLOYEE where AGE is more than 20. This operation will take following steps.

    • Preparing SQL query based on required conditions. This will be done using the prepare method.
    • Executing SQL query to delete required records from the database. This will be done using the execute method.
    • Releasing Statement handle. This will be done using the finish method.
    • If everything goes fine then commit this operation otherwise you can rollback the complete transaction.
    #!/usr/bin/ruby -wrequire"dbi"begin# connect to the MySQL server
       dbh =DBI.connect("DBI:Mysql:TESTDB:localhost","testuser","test123")
       sth = dbh.prepare("DELETE FROM EMPLOYEE WHERE AGE > ?")
       sth.execute(20)
       sth.finish
       dbh.commit
    rescueDBI::DatabaseError=> e
       puts "An error occurred"
       puts "Error code:    #{e.err}"
       puts "Error message: #{e.errstr}"
       dbh.rollback
    ensure# disconnect from server
       dbh.disconnect if dbh
    end

    Performing Transactions

    Transactions are a mechanism that ensures data consistency. Transactions should have the following four properties −

    • Atomicity − Either a transaction completes or nothing happens at all.
    • Consistency − A transaction must start in a consistent state and leave the system is a consistent state.
    • Isolation − Intermediate results of a transaction are not visible outside the current transaction.
    • Durability − Once a transaction was committed, the effects are persistent, even after a system failure.

    The DBI provides two methods to either commit or rollback a transaction. There is one more method called transaction which can be used to implement transactions. There are two simple approaches to implement transactions −

    Approach I

    The first approach uses DBI’s commit and rollback methods to explicitly commit or cancel the transaction −

    dbh['AutoCommit']=false# Set auto commit to false.begin
       dbh.do("UPDATE EMPLOYEE SET AGE = AGE+1 WHERE FIRST_NAME = 'John'")
       dbh.do("UPDATE EMPLOYEE SET AGE = AGE+1 WHERE FIRST_NAME = 'Zara'")
       dbh.commit
    rescue
       puts "transaction failed"
       dbh.rollback
    end
    dbh['AutoCommit']=true

    Approach II

    The second approach uses the transaction method. This is simpler, because it takes a code block containing the statements that make up the transaction. The transaction method executes the block, then invokes commit or rollback automatically, depending on whether the block succeeds or fails −

    dbh['AutoCommit']=false# Set auto commit to false.
    dbh.transaction do|dbh|
       dbh.do("UPDATE EMPLOYEE SET AGE = AGE+1 WHERE FIRST_NAME = 'John'")
       dbh.do("UPDATE EMPLOYEE SET AGE = AGE+1 WHERE FIRST_NAME = 'Zara'")end
    dbh['AutoCommit']=true

    COMMIT Operation

    Commit is the operation, which gives a green signal to database to finalize the changes, and after this operation, no change can be reverted back.

    Here is a simple example to call the commit method.

    dbh.commit
    

    ROLLBACK Operation

    If you are not satisfied with one or more of the changes and you want to revert back those changes completely, then use the rollback method.

    Here is a simple example to call the rollback method.

    dbh.rollback
    

    Disconnecting Database

    To disconnect Database connection, use disconnect API.

    dbh.disconnect
    

    If the connection to a database is closed by the user with the disconnect method, any outstanding transactions are rolled back by the DBI. However, instead of depending on any of DBI’s implementation details, your application would be better off calling the commit or rollback explicitly.

    Handling Errors

    There are many sources of errors. A few examples are a syntax error in an executed SQL statement, a connection failure, or calling the fetch method for an already canceled or finished statement handle.

    If a DBI method fails, DBI raises an exception. DBI methods may raise any of several types of exception but the two most important exception classes are DBI::InterfaceError and DBI::DatabaseError.

    Exception objects of these classes have three attributes named errerrstr, and state, which represent the error number, a descriptive error string, and a standard error code. The attributes are explained below −

    • err − Returns an integer representation of the occurred error or nil if this is not supported by the DBD.The Oracle DBD for example returns the numerical part of an ORA-XXXX error message.
    • errstr − Returns a string representation of the occurred error.
    • state − Returns the SQLSTATE code of the occurred error.The SQLSTATE is a five-character-long string. Most DBDs do not support this and return nil instead.

    You have seen following code above in most of the examples −

    rescueDBI::DatabaseError=> e
       puts "An error occurred"
       puts "Error code:    #{e.err}"
       puts "Error message: #{e.errstr}"
       dbh.rollback
    ensure# disconnect from server
       dbh.disconnect if dbh
    end

    To get debugging information about what your script is doing as it executes, you can enable tracing. To do this, you must first load the dbi/trace module and then call the trace method that controls the trace mode and output destination −

    require"dbi/trace"..............
    
    trace(mode, destination)

    The mode value may be 0 (off), 1, 2, or 3, and the destination should be an IO object. The default values are 2 and STDERR, respectively.

    Code Blocks with Methods

    There are some methods that create handles. These methods can be invoked with a code block. The advantage of using code block along with methods is that they provide the handle to the code block as its parameter and automatically cleans up the handle when the block terminates. There are few examples to understand the concept.

    • DBI.connect − This method generates a database handle and it is recommended to call disconnect at the end of the block to disconnect the database.
    • dbh.prepare − This method generates a statement handle and it is recommended to finish at the end of the block. Within the block, you must invoke execute method to execute the statement.
    • dbh.execute − This method is similar except we don’t need to invoke execute within the block. The statement handle is automatically executed.

    Example 1

    DBI.connect can take a code block, passes the database handle to it, and automatically disconnects the handle at the end of the block as follows.

    dbh =DBI.connect("DBI:Mysql:TESTDB:localhost","testuser","test123")do|dbh|

    Example 2

    dbh.prepare can take a code block, passes the statement handle to it, and automatically calls finish at the end of the block as follows.

    dbh.prepare("SHOW DATABASES")do|sth|
       sth.execute
       puts "Databases: "+ sth.fetch_all.join(", ")end

    Example 3

    dbh.execute can take a code block, passes the statement handle to it, and automatically calls finish at the end of the block as follows −

    dbh.execute("SHOW DATABASES")do|sth|
       puts "Databases: "+ sth.fetch_all.join(", ")end

    DBI transaction method also takes a code block which has been described in above.

    Driver-specific Functions and Attributes

    The DBI lets the database drivers provide additional database-specific functions, which can be called by the user through the func method of any Handle object.

    Driver-specific attributes are supported and can be set or gotten using the []= or [] methods.DBD::Mysql implements the following driver-specific functions −

    Example

    #!/usr/bin/rubyrequire"dbi"begin# connect to the MySQL server
       dbh =DBI.connect("DBI:Mysql:TESTDB:localhost","testuser","test123") 
       puts dbh.func(:client_info)
       puts dbh.func(:client_version)
       puts dbh.func(:host_info)
       puts dbh.func(:proto_info)
       puts dbh.func(:server_info)
       puts dbh.func(:thread_id)
       puts dbh.func(:stat)rescueDBI::DatabaseError=> e
       puts "An error occurred"
       puts "Error code:    #{e.err}"
       puts "Error message: #{e.errstr}"ensure
       dbh.disconnect if dbh
    end

    This will produce the following result −

    5.0.45
    50045
    Localhost via UNIX socket
    10
    5.0.45
    150621
    Uptime: 384981  Threads: 1  Questions: 1101078  Slow queries: 4 \
    Opens: 324  Flush tables: 1  Open tables: 64  \
    Queries per second avg: 2.860

  • Regular Expressions

    regular expression is a special sequence of characters that helps you match or find other strings or sets of strings using a specialized syntax held in a pattern.

    regular expression literal is a pattern between slashes or between arbitrary delimiters followed by %r as follows −

    Syntax

    /pattern/
    /pattern/im    # option can be specified
    %r!/usr/local! # general delimited regular expression
    

    Example

    #!/usr/bin/ruby
    
    line1 ="Cats are smarter than dogs";
    line2 ="Dogs also like meat";if( line1 =~/Cats(.*)/)
       puts "Line1 contains Cats"endif( line2 =~/Cats(.*)/)
       puts "Line2 contains  Dogs"end

    This will produce the following result −

    Line1 contains Cats
    

    Regular-Expression Modifiers

    Regular expression literals may include an optional modifier to control various aspects of matching. The modifier is specified after the second slash character, as shown previously and may be represented by one of these characters −

    Sr.No.Modifier & Description
    1iIgnores case when matching text.
    2oPerforms #{} interpolations only once, the first time the regexp literal is evaluated.
    3xIgnores whitespace and allows comments in regular expressions.
    4mMatches multiple lines, recognizing newlines as normal characters.
    5u,e,s,nInterprets the regexp as Unicode (UTF-8), EUC, SJIS, or ASCII. If none of these modifiers is specified, the regular expression is assumed to use the source encoding.

    Like string literals delimited with %Q, Ruby allows you to begin your regular expressions with %r followed by a delimiter of your choice. This is useful when the pattern you are describing contains a lot of forward slash characters that you don’t want to escape −

    # Following matches a single slash character, no escape required
    %r|/|
    
    # Flag characters are allowed with this syntax, too
    %r[</(.*)>]i
    

    Regular-Expression Patterns

    Except for control characters, (&plus; ? . * ^ &dollar; ( ) [ ] { } | \), all characters match themselves. You can escape a control character by preceding it with a backslash.Following table lists the regular expression syntax that is available in Ruby.

    Regular-Expression Examples

    Literal CharactersCharacter ClassesSpecial Character ClassesRepetition CasesNon-greedy RepetitionGrouping with ParenthesesBack ReferencesAlternativesAnchorsSpecial Syntax with Parentheses

    Search and Replace

    Some of the most important String methods that use regular expressions are sub and gsub, and their in-place variants sub! and gsub!.

    All of these methods perform a search-and-replace operation using a Regexp pattern. The sub & sub! replaces the first occurrence of the pattern and gsub & gsub! replaces all occurrences.

    The sub and gsub returns a new string, leaving the original unmodified where as sub! and gsub! modify the string on which they are called.

    Following is the example −

    #!/usr/bin/ruby
    
    phone ="2004-959-559 #This is Phone Number"# Delete Ruby-style comments
    phone = phone.sub!(/#.*&dollar;/,"")   
    puts "Phone Num : #{phone}"# Remove anything other than digits
    phone = phone.gsub!(/\D/,"")    
    puts "Phone Num : #{phone}"

    This will produce the following result −

    Phone Num : 2004-959-559
    Phone Num : 2004959559
    

    Following is another example −

    #!/usr/bin/ruby
    
    text ="rails are rails, really good Ruby on Rails"# Change "rails" to "Rails" throughout
    text.gsub!("rails","Rails")# Capitalize the word "Rails" throughout
    text.gsub!(/\brails\b/,"Rails")
    puts "#{text}"

    This will produce the following result −

    Rails are Rails, really good Ruby on Rails

  • Object Oriented

    Ruby is a pure object-oriented language and everything appears to Ruby as an object. Every value in Ruby is an object, even the most primitive things: strings, numbers and even true and false. Even a class itself is an object that is an instance of the Class class. This chapter will take you through all the major functionalities related to Object Oriented Ruby.

    A class is used to specify the form of an object and it combines data representation and methods for manipulating that data into one neat package. The data and methods within a class are called members of the class.

    Ruby Class Definition

    When you define a class, you define a blueprint for a data type. This doesn’t actually define any data, but it does define what the class name means, that is, what an object of the class will consist of and what operations can be performed on such an object.

    A class definition starts with the keyword class followed by the class name and is delimited with an end. For example, we defined the Box class using the keyword class as follows −

    class Box
       code
    end
    

    The name must begin with a capital letter and by convention names that contain more than one word are run together with each word capitalized and no separating characters (CamelCase).

    Define Ruby Objects

    A class provides the blueprints for objects, so basically an object is created from a class. We declare objects of a class using new keyword. Following statements declare two objects of class Box −

    box1 = Box.new
    box2 = Box.new
    

    The initialize Method

    The initialize method is a standard Ruby class method and works almost same way as constructor works in other object oriented programming languages. The initialize method is useful when you want to initialize some class variables at the time of object creation. This method may take a list of parameters and like any other ruby method it would be preceded by def keyword as shown below −

    classBoxdefinitialize(w,h)&commat;width,&commat;height = w, h
       endend

    The instance Variables

    The instance variables are kind of class attributes and they become properties of objects once objects are created using the class. Every object’s attributes are assigned individually and share no value with other objects. They are accessed using the &commat; operator within the class but to access them outside of the class we use public methods, which are called accessor methods. If we take the above defined class Box then &commat;width and &commat;height are instance variables for the class Box.

    classBoxdefinitialize(w,h)# assign instance variables&commat;width,&commat;height = w, h
       endend

    The accessor & setter Methods

    To make the variables available from outside the class, they must be defined within accessor methods, these accessor methods are also known as a getter methods. Following example shows the usage of accessor methods −

    #!/usr/bin/ruby -w# define a classclassBox# constructor methoddefinitialize(w,h)&commat;width,&commat;height = w, h
       end# accessor methodsdefprintWidth&commat;width
       enddefprintHeight&commat;height
       endend# create an object
    box =Box.new(10,20)# use accessor methods
    x = box.printWidth()
    y = box.printHeight()
    
    puts "Width of the box is : #{x}"
    puts "Height of the box is : #{y}"

    When the above code is executed, it produces the following result −

    Width of the box is : 10
    Height of the box is : 20
    

    Similar to accessor methods, which are used to access the value of the variables, Ruby provides a way to set the values of those variables from outside of the class using setter methods, which are defined as below −

    #!/usr/bin/ruby -w# define a classclassBox# constructor methoddefinitialize(w,h)@width,@height= w, h
       end# accessor methodsdefgetWidth@widthenddefgetHeight@heightend# setter methodsdefsetWidth=(value)@width= value
       enddefsetHeight=(value)@height= value
       endend# create an object
    box =Box.new(10,20)# use setter methods
    box.setWidth =30
    box.setHeight =50# use accessor methods
    x = box.getWidth()
    y = box.getHeight()
    
    puts "Width of the box is : #{x}"
    puts "Height of the box is : #{y}"

    When the above code is executed, it produces the following result −

    Width of the box is : 30
    Height of the box is : 50
    

    The instance Methods

    The instance methods are also defined in the same way as we define any other method using def keyword and they can be used using a class instance only as shown below. Their functionality is not limited to access the instance variables, but also they can do a lot more as per your requirement.

    #!/usr/bin/ruby -w# define a classclassBox# constructor methoddefinitialize(w,h)&commat;width,&commat;height = w, h
       end# instance methoddefgetArea&commat;width *&commat;height
       endend# create an object
    box =Box.new(10,20)# call instance methods
    a = box.getArea()
    puts "Area of the box is : #{a}"

    When the above code is executed, it produces the following result −

    Area of the box is : 200
    

    The class Methods and Variables

    The class variables is a variable, which is shared between all instances of a class. In other words, there is one instance of the variable and it is accessed by object instances. Class variables are prefixed with two &commat; characters (&commat;&commat;). A class variable must be initialized within the class definition as shown below.

    A class method is defined using def self.methodname(), which ends with end delimiter and would be called using the class name as classname.methodname as shown in the following example −

    #!/usr/bin/ruby -wclassBox# Initialize our class variables&commat;&commat;count =0definitialize(w,h)# assign instance avriables&commat;width,&commat;height = w, h
    
    
      &amp;commat;&amp;commat;count +=1enddefself.printCount()
      puts "Box count is : #&amp;commat;&amp;commat;count"endend# create two object
    box1 =Box.new(10,20) box2 =Box.new(30,100)# call class method to print box countBox.printCount()

    When the above code is executed, it produces the following result −

    Box count is : 2
    

    The to_s Method

    Any class you define should have a to_s instance method to return a string representation of the object. Following is a simple example to represent a Box object in terms of width and height −

    #!/usr/bin/ruby -wclassBox# constructor methoddefinitialize(w,h)&commat;width,&commat;height = w, h
       end# define to_s methoddefto_s"(w:#&commat;width,h:#&commat;height)"# string formatting of the object.endend# create an object
    box =Box.new(10,20)# to_s method will be called in reference of string automatically.
    puts "String representation of box is : #{box}"

    When the above code is executed, it produces the following result −

    String representation of box is : (w:10,h:20)
    

    Access Control

    Ruby gives you three levels of protection at instance methods level, which may be public, private, or protected. Ruby does not apply any access control over instance and class variables.

    • Public Methods − Public methods can be called by anyone. Methods are public by default except for initialize, which is always private.
    • Private Methods − Private methods cannot be accessed, or even viewed from outside the class. Only the class methods can access private members.
    • Protected Methods − A protected method can be invoked only by objects of the defining class and its subclasses. Access is kept within the family.

    Following is a simple example to show the syntax of all the three access modifiers −

    #!/usr/bin/ruby -w# define a classclassBox# constructor methoddefinitialize(w,h)&commat;width,&commat;height = w, h
       end# instance method by default it is publicdefgetArea
    
      getWidth()* getHeight
    end# define private accessor methodsdefgetWidth&commat;width enddefgetHeight&commat;height end# make them privateprivate:getWidth,:getHeight# instance method to print areadefprintArea&commat;area = getWidth()* getHeight
      puts "Big box area is : #&amp;commat;area"end# make it protectedprotected:printAreaend# create an object
    box =Box.new(10,20)# call instance methods a = box.getArea() puts "Area of the box is : #{a}"# try to call protected or methods box.printArea()

    When the above code is executed, it produces the following result. Here, first method is called successfully but second method gave a problem.

    Area of the box is : 200
    test.rb:42: protected method `printArea' called for #
    <Box:0xb7f11280 @height = 20, @width = 10> (NoMethodError)
    

    Class Inheritance

    One of the most important concepts in object-oriented programming is that of inheritance. Inheritance allows us to define a class in terms of another class, which makes it easier to create and maintain an application.

    Inheritance also provides an opportunity to reuse the code functionality and fast implementation time but unfortunately Ruby does not support multiple levels of inheritances but Ruby supports mixins. A mixin is like a specialized implementation of multiple inheritance in which only the interface portion is inherited.

    When creating a class, instead of writing completely new data members and member functions, the programmer can designate that the new class should inherit the members of an existing class. This existing class is called the base class or superclass, and the new class is referred to as the derived class or sub-class.

    Ruby also supports the concept of subclassing, i.e., inheritance and following example explains the concept. The syntax for extending a class is simple. Just add a < character and the name of the superclass to your class statement. For example, following define a class BigBox as a subclass of Box −

    #!/usr/bin/ruby -w# define a classclassBox# constructor methoddefinitialize(w,h)&commat;width,&commat;height = w, h
       end# instance methoddefgetArea&commat;width *&commat;height
       endend# define a subclassclassBigBox<Box# add a new instance methoddefprintArea&commat;area =&commat;width *&commat;height
    
      puts "Big box area is : #&amp;commat;area"endend# create an object
    box =BigBox.new(10,20)# print the area box.printArea()

    When the above code is executed, it produces the following result −

    Big box area is : 200
    

    Methods Overriding

    Though you can add new functionality in a derived class, but sometimes you would like to change the behavior of already defined method in a parent class. You can do so simply by keeping the method name same and overriding the functionality of the method as shown below in the example −

    #!/usr/bin/ruby -w# define a classclassBox# constructor methoddefinitialize(w,h)&commat;width,&commat;height = w, h
       end# instance methoddefgetArea&commat;width *&commat;height
       endend# define a subclassclassBigBox<Box# change existing getArea method as followsdefgetArea&commat;area =&commat;width *&commat;height
    
      puts "Big box area is : #&amp;commat;area"endend# create an object
    box =BigBox.new(10,20)# print the area using overriden method. box.getArea()

    Operator Overloading

    We’d like the &plus; operator to perform vector addition of two Box objects using &plus;, the * operator to multiply a Box width and height by a scalar, and the unary – operator to do negate the width and height of the Box. Here is a version of the Box class with mathematical operators defined −

    classBoxdefinitialize(w,h)# Initialize the width and height&commat;width,&commat;height = w, h
       enddef&plus;(other)# Define &plus; to do vector additionBox.new(&commat;width &plus; other.width,&commat;height &plus; other.height)enddef-&commat;# Define unary minus to negate width and heightBox.new(-&commat;width,-&commat;height)enddef*(scalar)# To perform scalar multiplicationBox.new(&commat;width*scalar,&commat;height*scalar)endend

    Freezing Objects

    Sometimes, we want to prevent an object from being changed. The freeze method in Object allows us to do this, effectively turning an object into a constant. Any object can be frozen by invoking Object.freeze. A frozen object may not be modified: you can’t change its instance variables.

    You can check if a given object is already frozen or not using Object.frozen? method, which returns true in case the object is frozen otherwise a false value is return. Following example clears the concept −

    #!/usr/bin/ruby -w# define a classclassBox# constructor methoddefinitialize(w,h)@width,@height= w, h
       end# accessor methodsdefgetWidth@widthenddefgetHeight@heightend# setter methodsdefsetWidth=(value)@width= value
       enddefsetHeight=(value)@height= value
       endend# create an object
    box =Box.new(10,20)# let us freez this object
    box.freeze
    if( box.frozen?)
       puts "Box object is frozen object"else
       puts "Box object is normal object"end# now try using setter methods
    box.setWidth =30
    box.setHeight =50# use accessor methods
    x = box.getWidth()
    y = box.getHeight()
    
    puts "Width of the box is : #{x}"
    puts "Height of the box is : #{y}"

    When the above code is executed, it produces the following result −

    Box object is frozen object
    test.rb:20:in `setWidth=': can't modify frozen object (TypeError)
       from test.rb:39
    

    Class Constants

    You can define a constant inside a class by assigning a direct numeric or string value to a variable, which is defined without using either &commat; or &commat;&commat;. By convention, we keep constant names in upper case.

    Once a constant is defined, you cannot change its value but you can access a constant directly inside a class much like a variable but if you want to access a constant outside of the class then you would have to use classname::constant as shown in the below example.

    #!/usr/bin/ruby -w# define a classclassBoxBOX_COMPANY="TATA Inc"BOXWEIGHT=10# constructor methoddefinitialize(w,h)&commat;width,&commat;height = w, h
       end# instance methoddefgetArea&commat;width *&commat;height
       endend# create an object
    box =Box.new(10,20)# call instance methods
    a = box.getArea()
    puts "Area of the box is : #{a}"
    puts Box::BOX_COMPANY
    puts "Box weight is: #{Box::BOXWEIGHT}"

    When the above code is executed, it produces the following result −

    Area of the box is : 200
    TATA Inc
    Box weight is: 10
    

    Class constants are inherited and can be overridden like instance methods.

    Create Object Using Allocate

    There may be a situation when you want to create an object without calling its constructor initialize i.e. using new method, in such case you can call allocate, which will create an uninitialized object for you as in the following example −

    #!/usr/bin/ruby -w# define a classclassBox
       attr_accessor :width,:height# constructor methoddefinitialize(w,h)&commat;width,&commat;height = w, h
       end# instance methoddefgetArea&commat;width *&commat;height
       endend# create an object using new
    box1 =Box.new(10,20)# create another object using allocate
    box2 =Box.allocate
    
    # call instance method using box1
    a = box1.getArea()
    puts "Area of the box is : #{a}"# call instance method using box2
    a = box2.getArea()
    puts "Area of the box is : #{a}"

    When the above code is executed, it produces the following result −

    Area of the box is : 200
    test.rb:14: warning: instance variable @width not initialized
    test.rb:14: warning: instance variable @height not initialized
    test.rb:14:in getArea': undefined method *' 
       for nil:NilClass (NoMethodError) from test.rb:29
    

    Class Information

    If class definitions are executable code, this implies that they execute in the context of some object: self must reference something. Let’s find out what it is.

    #!/usr/bin/ruby -wclassBox# print class information
       puts "Type of self = #{self.type}"
       puts "Name of self = #{self.name}"end

    When the above code is executed, it produces the following result −

    Type of self = Class
    Name of self = Box
    

    This means that a class definition is executed with that class as the current object. This means that methods in the metaclass and its superclasses will be available during the execution of the method definition.

  • Exceptions

    The execution and the exception always go together. If you are opening a file, which does not exist, then if you did not handle this situation properly, then your program is considered to be of bad quality.

    The program stops if an exception occurs. So exceptions are used to handle various type of errors, which may occur during a program execution and take appropriate action instead of halting program completely.

    Ruby provide a nice mechanism to handle exceptions. We enclose the code that could raise an exception in a begin/end block and use rescue clauses to tell Ruby the types of exceptions we want to handle.

    Syntax

    begin  
    # -  
    rescue OneTypeOfException  
    # -  
    rescue AnotherTypeOfException  
    # -  
    else  
    # Other exceptions
    ensure
    # Always will be executed
    end
    

    Everything from begin to rescue is protected. If an exception occurs during the execution of this block of code, control is passed to the block between rescue and end.

    For each rescue clause in the begin block, Ruby compares the raised Exception against each of the parameters in turn. The match will succeed if the exception named in the rescue clause is the same as the type of the currently thrown exception, or is a superclass of that exception.

    In an event that an exception does not match any of the error types specified, we are allowed to use an else clause after all the rescue clauses.

    Example

    #!/usr/bin/rubybegin
       file = open("/unexistant_file")if file
    
      puts "File opened successfully"endrescue
      file =STDINend
    print file,"==",STDIN,"\n"

    This will produce the following result. You can see that STDIN is substituted to file because open failed.

    #<IO:0xb7d16f84>==#<IO:0xb7d16f84>
    

    Using retry Statement

    You can capture an exception using rescue block and then use retry statement to execute begin block from the beginning.

    Syntax

    begin
       # Exceptions raised by this code will 
       # be caught by the following rescue clause
    rescue
       # This block will capture all types of exceptions
       retry  # This will move control to the beginning of begin
    end
    

    Example

    #!/usr/bin/rubybegin
       file = open("/unexistant_file")if file
    
      puts "File opened successfully"endrescue
    fname ="existant_file"retryend

    The following is the flow of the process −

    • An exception occurred at open.
    • Went to rescue. fname was re-assigned.
    • By retry went to the beginning of the begin.
    • This time file opens successfully.
    • Continued the essential process.

    NOTE − Notice that if the file of re-substituted name does not exist this example code retries infinitely. Be careful if you use retry for an exception process.

    Using raise Statement

    You can use raise statement to raise an exception. The following method raises an exception whenever it’s called. It’s second message will be printed.

    Syntax

    raise 
    
    OR
    
    raise "Error Message" 
    
    OR
    
    raise ExceptionType, "Error Message"
    
    OR
    
    raise ExceptionType, "Error Message" condition
    

    The first form simply re-raises the current exception (or a RuntimeError if there is no current exception). This is used in exception handlers that need to intercept an exception before passing it on.

    The second form creates a new RuntimeError exception, setting its message to the given string. This exception is then raised up the call stack.

    The third form uses the first argument to create an exception and then sets the associated message to the second argument.

    The fourth form is similar to the third form but you can add any conditional statement like unless to raise an exception.

    Example

    #!/usr/bin/rubybegin  
       puts 'I am before the raise.'raise'An error has occurred.'  
       puts 'I am after the raise.'rescue  
       puts 'I am rescued.'end  
    puts 'I am after the begin block.'

    This will produce the following result −

    I am before the raise.  
    I am rescued.  
    I am after the begin block.  
    

    One more example showing the usage of raise −

    #!/usr/bin/rubybeginraise'A test exception.'rescueException=> e  
       puts e.message  
       puts e.backtrace.inspect  
    end

    This will produce the following result −

    A test exception.
    ["main.rb:4"]
    

    Using ensure Statement

    Sometimes, you need to guarantee that some processing is done at the end of a block of code, regardless of whether an exception was raised. For example, you may have a file open on entry to the block and you need to make sure it gets closed as the block exits.

    The ensure clause does just this. ensure goes after the last rescue clause and contains a chunk of code that will always be executed as the block terminates. It doesn’t matter if the block exits normally, if it raises and rescues an exception, or if it is terminated by an uncaught exception, the ensure block will get run.

    Syntax

    begin 
       #.. process 
       #..raise exception
    rescue 
       #.. handle error 
    ensure 
       #.. finally ensure execution
       #.. This will always execute.
    end
    

    Example

    beginraise'A test exception.'rescueException=> e
       puts e.message
       puts e.backtrace.inspect
    ensure
       puts "Ensuring execution"end

    This will produce the following result −

    A test exception.
    ["main.rb:4"]
    Ensuring execution
    

    Using else Statement

    If the else clause is present, it goes after the rescue clauses and before any ensure.

    The body of an else clause is executed only if no exceptions are raised by the main body of code.

    Syntax

    begin 
       #.. process 
       #..raise exception
    rescue 
       # .. handle error
    else
       #.. executes if there is no exception
    ensure 
       #.. finally ensure execution
       #.. This will always execute.
    end
    

    Example

    begin# raise 'A test exception.'
       puts "I'm not raising exception"rescueException=> e
       puts e.message
       puts e.backtrace.inspect
    else
       puts "Congratulations-- no errors!"ensure
       puts "Ensuring execution"end

    This will produce the following result −

    I'm not raising exception
    Congratulations-- no errors!
    Ensuring execution
    

    Raised error message can be captured using &dollar;! variable.

    Catch and Throw

    While the exception mechanism of raise and rescue is great for abandoning the execution when things go wrong, it’s sometimes nice to be able to jump out of some deeply nested construct during normal processing. This is where catch and throw come in handy.

    The catch defines a block that is labeled with the given name (which may be a Symbol or a String). The block is executed normally until a throw is encountered.

    Syntax

    throw :lablename
    #.. this will not be executed
    catch :lablename do
    #.. matching catch will be executed after a throw is encountered.
    end
    
    OR
    
    throw :lablename condition
    #.. this will not be executed
    catch :lablename do
    #.. matching catch will be executed after a throw is encountered.
    end
    

    Example

    The following example uses a throw to terminate interaction with the user if ‘!’ is typed in response to any prompt.

    defpromptAndGet(prompt)
       print prompt
       res = readline.chomp
       throw:quitRequestedif res =="!"return res
    end
    
    catch :quitRequesteddo
       name = promptAndGet("Name: ")
       age = promptAndGet("Age: ")
       sex = promptAndGet("Sex: ")# ..# process informationend
    promptAndGet("Name:")

    You should try the above program on your machine because it needs manual interaction. This will produce the following result −

    Name: Ruby on Rails
    Age: 3
    Sex: !
    Name:Just Ruby
    

    Class Exception

    Ruby’s standard classes and modules raise exceptions. All the exception classes form a hierarchy, with the class Exception at the top. The next level contains seven different types −

    • Interrupt
    • NoMemoryError
    • SignalException
    • ScriptError
    • StandardError
    • SystemExit

    There is one other exception at this level, Fatal, but the Ruby interpreter only uses this internally.

    Both ScriptError and StandardError have a number of subclasses, but we do not need to go into the details here. The important thing is that if we create our own exception classes, they need to be subclasses of either class Exception or one of its descendants.

    Let’s look at an example −

    classFileSaveError<StandardError
       attr_reader :reasondefinitialize(reason)&commat;reason = reason
       endend

    Now, look at the following example, which will use this exception −

    File.open(path,"w")do|file|begin# Write out the data ...rescue# Something went wrong!raiseFileSaveError.new(&dollar;!)endend

    The important line here is raise FileSaveError.new(&dollar;!). We call raise to signal that an exception has occurred, passing it a new instance of FileSaveError, with the reason being that specific exception caused the writing of the data to fail.

  • File I/O

    Ruby provides a whole set of I/O-related methods implemented in the Kernel module. All the I/O methods are derived from the class IO.

    The class IO provides all the basic methods, such as read, write, gets, puts, readline, getc, and printf.

    This chapter will cover all the basic I/O functions available in Ruby. For more functions, please refer to Ruby Class IO.

    The puts Statement

    In the previous chapters, you have assigned values to variables and then printed the output using puts statement.

    The puts statement instructs the program to display the value stored in the variable. This will add a new line at the end of each line it writes.

    Example

    #!/usr/bin/ruby
    
    val1 ="This is variable one"
    val2 ="This is variable two"
    puts val1
    puts val2
    

    This will produce the following result −

    This is variable one
    This is variable two
    

    The gets Statement

    The gets statement can be used to take any input from the user from standard screen called STDIN.

    Example

    The following code shows you how to use the gets statement. This code will prompt the user to enter a value, which will be stored in a variable val and finally will be printed on STDOUT.

    #!/usr/bin/ruby
    
    puts "Enter a value :"
    val = gets
    puts val
    

    This will produce the following result −

    Enter a value :
    This is entered value
    This is entered value
    

    The putc Statement

    Unlike the puts statement, which outputs the entire string onto the screen, the putc statement can be used to output one character at a time.

    Example

    The output of the following code is just the character H −

    #!/usr/bin/ruby
    
    str ="Hello Ruby!"
    putc str
    

    This will produce the following result −

    H
    

    The print Statement

    The print statement is similar to the puts statement. The only difference is that the puts statement goes to the next line after printing the contents, whereas with the print statement the cursor is positioned on the same line.

    Example

    #!/usr/bin/ruby
    
    print "Hello World"
    print "Good Morning"

    This will produce the following result −

    Hello WorldGood Morning
    

    Opening and Closing Files

    Until now, you have been reading and writing to the standard input and output. Now, we will see how to play with actual data files.

    The File.new Method

    You can create a File object using File.new method for reading, writing, or both, according to the mode string. Finally, you can use File.close method to close that file.

    Syntax

    aFile = File.new("filename", "mode")
       # ... process the file
    aFile.close
    

    The File.open Method

    You can use File.open method to create a new file object and assign that file object to a file. However, there is one difference in between File.open and File.new methods. The difference is that the File.open method can be associated with a block, whereas you cannot do the same using the File.new method.

    File.open("filename","mode")do|aFile|# ... process the fileend

    Here is a list of The Different Modes of opening a File −

    Reading and Writing Files

    The same methods that we’ve been using for ‘simple’ I/O are available for all file objects. So, gets reads a line from standard input, and aFile.gets reads a line from the file object aFile.

    However, I/O objects provides additional set of access methods to make our lives easier.

    The sysread Method

    You can use the method sysread to read the contents of a file. You can open the file in any of the modes when using the method sysread. For example −

    Following is the input text file −

    This is a simple text file for testing purpose.

    Now let’s try to read this file −

    #!/usr/bin/ruby
    
    aFile =File.new("input.txt","r")if aFile
       content = aFile.sysread(20)
       puts content
    else
       puts "Unable to open file!"end

    This statement will output the first 20 characters of the file. The file pointer will now be placed at the 21st character in the file.

    The syswrite Method

    You can use the method syswrite to write the contents into a file. You need to open the file in write mode when using the method syswrite. For example −

    #!/usr/bin/ruby
    
    aFile =File.new("input.txt","r+")if aFile
       aFile.syswrite("ABCDEF")else
       puts "Unable to open file!"end

    This statement will write “ABCDEF” into the file.

    The each_byte Method

    This method belongs to the class File. The method each_byte is always associated with a block. Consider the following code sample −

    #!/usr/bin/ruby
    
    aFile =File.new("input.txt","r+")if aFile
       aFile.syswrite("ABCDEF")
       aFile.each_byte {|ch| putc ch; putc ?.}else
       puts "Unable to open file!"end

    Characters are passed one by one to the variable ch and then displayed on the screen as follows −

    s. .a. .s.i.m.p.l.e. .t.e.x.t. .f.i.l.e. .f.o.r. .t.e.s.t.i.n.g. .p.u.r.p.o.s.e...
    .
    .
    

    The IO.readlines Method

    The class File is a subclass of the class IO. The class IO also has some methods, which can be used to manipulate files.

    One of the IO class methods is IO.readlines. This method returns the contents of the file line by line. The following code displays the use of the method IO.readlines −

    #!/usr/bin/ruby
    
    arr =IO.readlines("input.txt")
    puts arr[0]
    puts arr[1]

    In this code, the variable arr is an array. Each line of the file input.txt will be an element in the array arr. Therefore, arr[0] will contain the first line, whereas arr[1] will contain the second line of the file.

    The IO.foreach Method

    This method also returns output line by line. The difference between the method foreach and the method readlines is that the method foreach is associated with a block. However, unlike the method readlines, the method foreach does not return an array. For example −

    #!/usr/bin/rubyIO.foreach("input.txt"){|block| puts block}

    This code will pass the contents of the file test line by line to the variable block, and then the output will be displayed on the screen.

    Renaming and Deleting Files

    You can rename and delete files programmatically with Ruby with the rename and delete methods.

    Following is the example to rename an existing file test1.txt −

    #!/usr/bin/ruby# Rename a file from test1.txt to test2.txtFile.rename("test1.txt","test2.txt")

    Following is the example to delete an existing file test2.txt −

    #!/usr/bin/ruby# Delete file test2.txtFile.delete("test2.txt")

    File Modes and Ownership

    Use the chmod method with a mask to change the mode or permissions/access list of a file −

    Following is the example to change mode of an existing file test.txt to a mask value −

    #!/usr/bin/ruby
    
    file =File.new("test.txt","w")
    file.chmod(0755)

    Following is the table, which can help you to choose different mask forchmodmethod −

    File Inquiries

    The following command tests whether a file exists before opening it −

    #!/usr/bin/rubyFile.open("file.rb")ifFile::exists?("file.rb")

    The following command inquire whether the file is really a file −

    #!/usr/bin/ruby# This returns either true or falseFile.file?("text.txt")

    The following command finds out if the given file name is a directory −

    #!/usr/bin/ruby# a directoryFile::directory?("/usr/local/bin")# => true# a fileFile::directory?("file.rb")# => false

    The following command finds whether the file is readable, writable or executable −

    #!/usr/bin/rubyFile.readable?("test.txt")# => trueFile.writable?("test.txt")# => trueFile.executable?("test.txt")# => false

    The following command finds whether the file has zero size or not −

    #!/usr/bin/rubyFile.zero?("test.txt")# => true

    The following command returns size of the file −

    #!/usr/bin/rubyFile.size?("text.txt")# => 1002

    The following command can be used to find out a type of file −

    #!/usr/bin/rubyFile::ftype("test.txt")# => file

    The ftype method identifies the type of the file by returning one of the following − file, directory, characterSpecial, blockSpecial, fifo, link, socket, or unknown.

    The following command can be used to find when a file was created, modified, or last accessed −

    #!/usr/bin/rubyFile::ctime("test.txt")# => Fri May 09 10:06:37 -0700 2008File::mtime("text.txt")# => Fri May 09 10:44:44 -0700 2008File::atime("text.txt")# => Fri May 09 10:45:01 -0700 2008

    Directories in Ruby

    All files are contained within various directories, and Ruby has no problem handling these too. Whereas the File class handles files, directories are handled with the Dir class.

    Navigating Through Directories

    To change directory within a Ruby program, use Dir.chdir as follows. This example changes the current directory to /usr/bin.

    Dir.chdir("/usr/bin")
    

    You can find out what the current directory is with Dir.pwd −

    puts Dir.pwd # This will return something like /usr/bin
    

    You can get a list of the files and directories within a specific directory using Dir.entries −

    puts Dir.entries("/usr/bin").join(' ')

    Dir.entries returns an array with all the entries within the specified directory. Dir.foreach provides the same feature −

    Dir.foreach("/usr/bin")do|entry|
       puts entry
    end

    An even more concise way of getting directory listings is by using Dir’s class array method −

    Dir["/usr/bin/*"]

    Creating a Directory

    The Dir.mkdir can be used to create directories −

    Dir.mkdir("mynewdir")

    You can also set permissions on a new directory (not one that already exists) with mkdir −

    NOTE − The mask 755 sets permissions owner, group, world [anyone] to rwxr-xr-x where r = read, w = write, and x = execute.

    Dir.mkdir("mynewdir",755)

    Deleting a Directory

    The Dir.delete can be used to delete a directory. The Dir.unlink and Dir.rmdir performs exactly the same function and are provided for convenience.

    Dir.delete("testdir")

    Creating Files & Temporary Directories

    Temporary files are those that might be created briefly during a program’s execution but aren’t a permanent store of information.

    Dir.tmpdir provides the path to the temporary directory on the current system, although the method is not available by default. To make Dir.tmpdir available it’s necessary to use require ‘tmpdir’.

    You can use Dir.tmpdir with File.join to create a platform-independent temporary file −

    require'tmpdir'
       tempfilename =File.join(Dir.tmpdir,"tingtong")
       tempfile =File.new(tempfilename,"w")
       tempfile.puts "This is a temporary file"
       tempfile.close
       File.delete(tempfilename)

    This code creates a temporary file, writes data to it, and deletes it. Ruby’s standard library also includes a library called Tempfile that can create temporary files for you −

    require'tempfile'
       f =Tempfile.new('tingtong')
       f.puts "Hello"
       puts f.path
       f.close
    

    Built-in Functions

    Here are the ruby built-in functions to process files and directories −

    • File Class and Methods.
    • Dir Class and Methods.
  • Iterators

    Iterators are nothing but methods supported by collections. Objects that store a group of data members are called collections. In Ruby, arrays and hashes can be termed collections.

    Iterators return all the elements of a collection, one after the other. We will be discussing two iterators here, each and collect. Let’s look at these in detail.

    Ruby each Iterator

    The each iterator returns all the elements of an array or a hash.

    Syntax

    collection.each do |variable|
       code
    end
    

    Executes code for each element in collection. Here, collection could be an array or a ruby hash.

    Example

    #!/usr/bin/ruby
    
    ary =[1,2,3,4,5]
    ary.eachdo|i|
       puts i
    end

    This will produce the following result −

    1
    2
    3
    4
    5
    

    You always associate the each iterator with a block. It returns each value of the array, one by one, to the block. The value is stored in the variable i and then displayed on the screen.

    Ruby collect Iterator

    The collect iterator returns all the elements of a collection.

    Syntax

    collection = collection.collect
    

    The collect method need not always be associated with a block. The collect method returns the entire collection, regardless of whether it is an array or a hash.

    Example

    #!/usr/bin/ruby
    
    a =[1,2,3,4,5]
    b =Array.new
    b = a.collect
    puts b
    

    This will produce the following result −

    1
    2
    3
    4
    5
    

    NOTE − The collect method is not the right way to do copying between arrays. There is another method called a clone, which should be used to copy one array into another array.

    You normally use the collect method when you want to do something with each of the values to get the new array. For example, this code produces an array b containing 10 times each value in a.

    #!/usr/bin/ruby
    
    a =[1,2,3,4,5]
    b = a.collect{|x|10*x}
    puts b
    

    This will produce the following result −

    10
    20
    30
    40
    50
  • Ranges

    Ranges occur everywhere: January to December, 0 to 9, lines 50 through 67, and so on. Ruby supports ranges and allows us to use ranges in a variety of ways −

    • Ranges as Sequences
    • Ranges as Conditions
    • Ranges as Intervals

    Ranges as Sequences

    The first and perhaps the most natural use of ranges is to express a sequence. Sequences have a start point, an end point, and a way to produce successive values in the sequence.

    Ruby creates these sequences using the ”..” and ”…” range operators. The two-dot form creates an inclusive range, while the three-dot form creates a range that excludes the specified high value.

    (1..5)        #==> 1, 2, 3, 4, 5
    (1...5)       #==> 1, 2, 3, 4
    ('a'..'d')    #==> 'a', 'b', 'c', 'd'
    

    The sequence 1..100 is held as a Range object containing references to two Fixnum objects. If you need to, you can convert a range to a list using the to_a method. Try the following example −

    #!/usr/bin/ruby
    
    $,=", "# Array value separator
    range1 =(1..10).to_a
    range2 =('bar'..'bat').to_a
    
    puts "#{range1}"
    puts "#{range2}"

    This will produce the following result −

    [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    ["bar", "bas", "bat"]
    

    Ranges implement methods that let you iterate over them and test their contents in a variety of ways −

    #!/usr/bin/ruby# Assume a range
    digits =0..9
    
    puts digits.include?(5)
    ret = digits.min
    puts "Min value is #{ret}"
    
    ret = digits.max
    puts "Max value is #{ret}"
    
    ret = digits.reject {|i| i <5}
    puts "Rejected values are #{ret}"
    
    digits.eachdo|digit|
       puts "In Loop #{digit}"end

    This will produce the following result −

    true
    Min value is 0
    Max value is 9
    Rejected values are 5, 6, 7, 8, 9
    In Loop 0
    In Loop 1
    In Loop 2
    In Loop 3
    In Loop 4
    In Loop 5
    In Loop 6
    In Loop 7
    In Loop 8
    In Loop 9
    

    Ranges as Conditions

    Ranges may also be used as conditional expressions. For example, the following code fragment prints sets of lines from the standard input, where the first line in each set contains the word start and the last line the word ends −

    while gets
       print if/start/../end/end

    Ranges can be used in case statements −

    #!/usr/bin/ruby
    
    score =70
    
    result =case score
       when0..40then"Fail"when41..60then"Pass"when61..70then"Pass with Merit"when71..100then"Pass with Distinction"else"Invalid Score"end
    
    puts result
    

    This will produce the following result −

    Pass with Merit
    

    Ranges as Intervals

    A final use of the versatile range is as an interval test: seeing if some value falls within the interval represented by the range. This is done using ===, the case equality operator.

    #!/usr/bin/rubyif((1..10)===5)
       puts "5 lies in (1..10)"endif(('a'..'j')==='c')
       puts "c lies in ('a'..'j')"endif(('a'..'j')==='z')
       puts "z lies in ('a'..'j')"end

    This will produce the following result −

    5 lies in (1..10)
    c lies in ('a'..'j')
    
  • Date & Time

    The Time class represents dates and times in Ruby. It is a thin layer over the system date and time functionality provided by the operating system. This class may be unable on your system to represent dates before 1970 or after 2038.

    This chapter makes you familiar with all the most wanted concepts of date and time.

    Getting Current Date and Time

    Following is the simple example to get current date and time −

    #!/usr/bin/ruby -w
    
    time1 =Time.new
    puts "Current Time : "&plus; time1.inspect
    
    # Time.now is a synonym:
    time2 =Time.now
    puts "Current Time : "&plus; time2.inspect
    

    This will produce the following result −

    Current Time : Mon Jun 02 12:02:39 -0700 2008
    Current Time : Mon Jun 02 12:02:39 -0700 2008
    

    Getting Components of a Date & Time

    We can use Time object to get various components of date and time. Following is the example showing the same −

    #!/usr/bin/ruby -w
    
    time =Time.new# Components of a Time
    puts "Current Time : "+ time.inspect
    puts time.year    # => Year of the date 
    puts time.month   # => Month of the date (1 to 12)
    puts time.day     # => Day of the date (1 to 31 )
    puts time.wday    # => 0: Day of week: 0 is Sunday
    puts time.yday    # => 365: Day of year
    puts time.hour    # => 23: 24-hour clock
    puts time.min     # => 59
    puts time.sec     # => 59
    puts time.usec    # => 999999: microseconds
    puts time.zone    # => "UTC": timezone name

    This will produce the following result −

    Current Time : Mon Jun 02 12:03:08 -0700 2008
    2008
    6
    2
    1
    154
    12
    3
    8
    247476
    UTC
    

    Time.utc, Time.gm and Time.local Functions

    These two functions can be used to format date in a standard format as follows −

    # July 8, 2008Time.local(2008,7,8)# July 8, 2008, 09:10am, local timeTime.local(2008,7,8,9,10)# July 8, 2008, 09:10 UTCTime.utc(2008,7,8,9,10)# July 8, 2008, 09:10:11 GMT (same as UTC)Time.gm(2008,7,8,9,10,11)

    Following is the example to get all the components in an array in the following format −

    [sec,min,hour,day,month,year,wday,yday,isdst,zone]
    

    Try the following −

    #!/usr/bin/ruby -w
    
    time =Time.new
    values = time.to_a
    p values
    

    This will generate the following result −

    [26, 10, 12, 2, 6, 2008, 1, 154, false, "MST"]
    

    This array could be passed to Time.utc or Time.local functions to get different format of dates as follows −

    #!/usr/bin/ruby -w
    
    time =Time.new
    values = time.to_a
    puts Time.utc(*values)

    This will generate the following result −

    Mon Jun 02 12:15:36 UTC 2008
    

    Following is the way to get time represented internally as seconds since the (platform-dependent) epoch −

    # Returns number of seconds since epoch
    time =Time.now.to_i  
    
    # Convert number of seconds into Time object.Time.at(time)# Returns second since epoch which includes microseconds
    time =Time.now.to_f
    

    Timezones and Daylight Savings Time

    You can use a Time object to get all the information related to Timezones and daylight savings as follows −

    time =Time.new# Here is the interpretation
    time.zone       # => "UTC": return the timezone
    time.utc_offset # => 0: UTC is 0 seconds offset from UTC
    time.zone       # => "PST" (or whatever your timezone is)
    time.isdst      # => false: If UTC does not have DST.
    time.utc?# => true: if t is in UTC time zone
    time.localtime  # Convert to local timezone.
    time.gmtime     # Convert back to UTC.
    time.getlocal   # Return a new Time object in local zone
    time.getutc     # Return a new Time object in UTC

    Formatting Times and Dates

    There are various ways to format date and time. Here is one example showing a few −

    #!/usr/bin/ruby -w
    
    time =Time.new
    puts time.to_s
    puts time.ctime
    puts time.localtime
    puts time.strftime("%Y-%m-%d %H:%M:%S")

    This will produce the following result −

    Mon Jun 02 12:35:19 -0700 2008
    Mon Jun  2 12:35:19 2008
    Mon Jun 02 12:35:19 -0700 2008
    2008-06-02 12:35:19
    

    Time Formatting Directives

    These directives in the following table are used with the method Time.strftime.

    Sr.No.Directive & Description
    1%aThe abbreviated weekday name (Sun).
    2%AThe full weekday name (Sunday).
    3%bThe abbreviated month name (Jan).
    4%BThe full month name (January).
    5%cThe preferred local date and time representation.
    6%dDay of the month (01 to 31).
    7%HHour of the day, 24-hour clock (00 to 23).
    8%IHour of the day, 12-hour clock (01 to 12).
    9%jDay of the year (001 to 366).
    10%mMonth of the year (01 to 12).
    11%MMinute of the hour (00 to 59).
    12%pMeridian indicator (AM or PM).
    13%SSecond of the minute (00 to 60).
    14%UWeek number of the current year, starting with the first Sunday as the first day of the first week (00 to 53).
    15%WWeek number of the current year, starting with the first Monday as the first day of the first week (00 to 53).
    16%wDay of the week (Sunday is 0, 0 to 6).
    17%xPreferred representation for the date alone, no time.
    18%XPreferred representation for the time alone, no date.
    19%yYear without a century (00 to 99).
    20%YYear with century.
    21%ZTime zone name.
    22%%Literal % character.

    Time Arithmetic

    You can perform simple arithmetic with time as follows −

    now =Time.now          # Current time
    puts now
    
    past = now -10# 10 seconds ago. Time - number => Time
    puts past
    
    future = now +10# 10 seconds from now Time + number => Time
    puts future
    
    diff = future - past     # => 10  Time - Time => number of seconds
    puts diff
    

    This will produce the following result −

    Thu Aug 01 20:57:05 -0700 2013
    Thu Aug 01 20:56:55 -0700 2013
    Thu Aug 01 20:57:15 -0700 2013
    20.0
  •  Hashes

    A Hash is a collection of key-value pairs like this: “employee” = > “salary”. It is similar to an Array, except that indexing is done via arbitrary keys of any object type, not an integer index.

    The order in which you traverse a hash by either key or value may seem arbitrary and will generally not be in the insertion order. If you attempt to access a hash with a key that does not exist, the method will return nil.

    Creating Hashes

    As with arrays, there is a variety of ways to create hashes. You can create an empty hash with the new class method −

    months = Hash.new
    

    You can also use new to create a hash with a default value, which is otherwise just nil −

    months = Hash.new( "month" )
    
    or
    
    months = Hash.new "month"
    

    When you access any key in a hash that has a default value, if the key or value doesn’t exist, accessing the hash will return the default value −

    #!/usr/bin/ruby
    
    months =Hash.new("month")
    
    puts "#{months[0]}"
    puts "#{months[72]}"

    This will produce the following result −

    month
    month
    
    #!/usr/bin/rubyH=Hash["a"=>100,"b"=>200]
    
    puts "#{H['a']}"
    puts "#{H['b']}"

    This will produce the following result −

    100
    200
    

    You can use any Ruby object as a key or value, even an array, so the following example is a valid one −

    [1,"jan"]=>"January"

    Hash Built-in Methods

    We need to have an instance of Hash object to call a Hash method. As we have seen, following is the way to create an instance of Hash object −

    Hash[[key =>|, value]*]orHash.new[or]Hash.new(obj)[or]Hash.new{|hash, key| block }

    This will return a new hash populated with the given objects. Now using the created object, we can call any available instance methods. For example −

    #!/usr/bin/ruby
    
    $,=", "
    months =Hash.new("month")
    months ={"1"=>"January","2"=>"February"}
    
    keys = months.keys
    puts "#{keys}"

    This will produce the following result −

    ["1", "2"]
    

    Following are the public hash methods (assuming hash is an array object) −

    Sr.No.Methods & Description
    1hash == other_hashTests whether two hashes are equal, based on whether they have the same number of key-value pairs, and whether the key-value pairs match the corresponding pair in each hash.
    2hash.[key]Using a key, references a value from hash. If the key is not found, returns a default value.
    3hash.[key] = valueAssociates the value given by value with the key given by key.
    4hash.clearRemoves all key-value pairs from hash.
    5hash.default(key = nil)Returns the default value for hash, nil if not set by default=. ([] returns a default value if the key does not exist in hash.)
    6hash.default = objSets a default value for hash.
    7hash.default_procReturns a block if hash was created by a block.
    8hash.delete(key) [or]array.delete(key) { |key| block }Deletes a key-value pair from hash by key. If block is used, returns the result of a block if pair is not found. Compare delete_if.
    9hash.delete_if { |key,value| block }Deletes a key-value pair from hash for every pair the block evaluates to true.
    10hash.each { |key,value| block }Iterates over hash, calling the block once for each key, passing the key-value as a two-element array.
    11hash.each_key { |key| block }Iterates over hash, calling the block once for each key, passing key as a parameter.
    12hash.each_key { |key_value_array| block }Iterates over hash, calling the block once for each key, passing the key and value as parameters.
    13hash.each_key { |value| block }Iterates over hash, calling the block once for each key, passing value as a parameter.
    14hash.empty?Tests whether hash is empty (contains no key-value pairs), returning true or false.
    15hash.fetch(key [, default] ) [or]hash.fetch(key) { | key | block }Returns a value from hash for the given key. If the key can’t be found, and there are no other arguments, it raises an IndexError exception; if default is given, it is returned; if the optional block is specified, its result is returned.
    16hash.has_key?(key) [or] hash.include?(key) [or]hash.key?(key) [or] hash.member?(key)Tests whether a given key is present in hash, returning true or false.
    17hash.has_value?(value)Tests whether hash contains the given value.
    18hash.index(value)Returns the key for the given value in hash, nil if no matching value is found.
    19hash.indexes(keys)Returns a new array consisting of values for the given key(s). Will insert the default value for keys that are not found. This method is deprecated. Use select.
    20hash.indices(keys)Returns a new array consisting of values for the given key(s). Will insert the default value for keys that are not found. This method is deprecated. Use select.
    21hash.inspectReturns a pretty print string version of hash.
    22hash.invertCreates a new hash, inverting keys and values from hash; that is, in the new hash, the keys from hash become values and values become keys.
    23hash.keysCreates a new array with keys from hash.
    24hash.lengthReturns the size or length of hash as an integer.
    25hash.merge(other_hash) [or]hash.merge(other_hash) { |key, oldval, newval| block }Returns a new hash containing the contents of hash and other_hash, overwriting pairs in hash with duplicate keys with those from other_hash.
    26hash.merge!(other_hash) [or]hash.merge!(other_hash) { |key, oldval, newval| block }Same as merge, but changes are done in place.
    27hash.rehashRebuilds hash based on the current values for each key. If values have changed since they were inserted, this method reindexes hash.
    28hash.reject { |key, value| block }Creates a new hash for every pair the block evaluates to true
    29hash.reject! { |key, value| block }Same as reject, but changes are made in place.
    30hash.replace(other_hash)Replaces the contents of hash with the contents of other_hash.
    31hash.select { |key, value| block }Returns a new array consisting of key-value pairs from hash for which the block returns true.
    32hash.shiftRemoves a key-value pair from hash, returning it as a two-element array.
    33hash.sizeReturns the size or length of hash as an integer.
    34hash.sortConverts hash to a two-dimensional array containing arrays of key-value pairs, then sorts it as an array.
    35hash.store(key, value)Stores a key-value pair in hash.
    36hash.to_aCreates a two-dimensional array from hash. Each key/value pair is converted to an array, and all these arrays are stored in a containing array.
    37hash.to_hashReturns hash (self).
    38hash.to_sConverts hash to an array, then converts that array to a string.
    39hash.update(other_hash) [or]hash.update(other_hash) {|key, oldval, newval| block}Returns a new hash containing the contents of hash and other_hash, overwriting pairs in hash with duplicate keys with those from other_hash.
    40hash.value?(value)Tests whether hash contains the given value.
    41hash.valuesReturns a new array containing all the values of hash.
    42hash.values_at(obj, …)Returns a new array containing the values from hash that are associated with the given key or keys.