Thursday, January 20, 2011

Web Application Testing in Ruby: Catch and Throw

Web Application Testing in Ruby: Web Application Testing in Ruby: What is Ecxeption in Ruby??

Catch and Throw
The catch and throw keywords enable you to jump up the error stack, thereby in effect performing a goto. If you can think of a good reason to do this, research these two keywords on your own. Personally, I'd prefer to stay away from them.

We've just scratched the surface of exception handling, but you probably have enough now to at least write simple exceptions and read other people's exception code.
Terminal IO
This section will cover just a few of the many ways you can do terminal IO. You've already learned about print and puts:
#!/usr/bin/ruby
print "This is the first half of Line 1. "
print "This is the second half.", "\n"
puts "This is line 2, no newline necessary."

The preceding code produces the following result:
[slitt@mydesk slitt]$ ./hello.rb
This is the first half of Line 1. This is the second half.
This is line 2, no newline necessary.
[slitt@mydesk slitt]$

Ruby has a printf() command similar to C:
#!/usr/bin/ruby
printf "There were %7d people at the %s.\n", 439, "Avalanche Auditorium"
[slitt@mydesk slitt]$ ./hello.rb
There were 439 people at the Avalanche Auditorium.
[slitt@mydesk slitt]$

You get line oriented keyboard input with gets:
#!/usr/bin/ruby
print "Name please=>"
name = gets
print "Your name is ", name, "\n"
[slitt@mydesk slitt]$ ./hello.rb
Name please=>Steve Litt
Your name is Steve Litt

[slitt@mydesk slitt]$

You can get a single character with gets(). However, the user will need to press the Enter key before gets() will accept the character. To enable instantaneous recognition of the character, you must set cbreak before gets() and then reset it afterwards, like this:
#!/usr/bin/ruby
print "Character please=>"
system "stty cbreak /dev/tty 2>&1";
int = STDIN.getc
system "stty -cbreak /dev/tty 2>&1";
print "\nYou pressed >", int, "<, char >", int.chr, "<\n"
[slitt@mydesk slitt]$ ./hello.rb
Character please=>A
You pressed >65<, char >A<
[slitt@mydesk slitt]$

The cbreak commands seem to work on modern Linuces. They are VERY system dependent, and as far as I know don't work on Windows at all. On some Unices you might try these instead:
system "stty", '-icanon', 'eol', "\001";
int = STDIN.getc
system "stty", 'icanon', 'eol', '^@'; # ASCII null
Terminal I/O is pretty simple in Ruby. So is file I/O...
File IO
File I/O uses the File object. It's very straightforward, as you can see from the following program, which opens resolv.conf for input, andjunk.jnk for output, and then copies each line from the input file to the output file:
#!/usr/bin/ruby
infile = File.new("/etc/resolv.conf", "r")
outfile = File.new("junk.jnk", "w")
infile.each {
|i|
outfile.write i
}
outfile.close()
infile.close()

outfile = File.new("junk.jnk", "r")
outfile.each {
|i|
print ">>", i
}
[slitt@mydesk slitt]$ ./hello.rb
>>search domain.cxm
>>nameserver 192.168.100.103
>>
>># ppp temp entry
[slitt@mydesk slitt]$

Perl has a way to immediately read a whole file into an array, and so does Ruby:
#!/usr/bin/ruby
infile = File.new("/etc/resolv.conf", "r")
linearray = infile.readlines
linearray.each{|i| print i}
infile.close
[slitt@mydesk slitt]$ ./hello.rb
search domain.cxm
nameserver 192.168.100.103

# ppp temp entry
[slitt@mydesk slitt]$

Ruby can no also read one character at a time:
#!/usr/bin/ruby
infile = File.new("/etc/resolv.conf", "r")
infile.each_byte {
|i|
if i.chr == "e"
print("!")
else
print(i.chr)
end
}
infile.close
[slitt@mydesk slitt]$ ./hello.rb
s!arch domain.cxm
nam!s!rv!r 192.168.100.103

# ppp t!mp !ntry
[slitt@mydesk slitt]

If for some reason you don't want to use the each construct, you can use readchar like this:
#!/usr/bin/ruby
infile = File.new("/etc/resolv.conf", "r")
until infile.eof
i = infile.readchar
if i.chr == "e"
print("!")
else
print(i.chr)
end
end
infile.close

In the preceding code, the eof method looks ahead to see whether the next character read will be valid, and if so, loops through, reads and prints it. You might think of doing a priming read, then putting the next read at the bottom of the loop, testing for i==nil. Unfortunately, if you read into the end of file, it triggers an exception which prints an error message, and nobody wants that. Instead, use eof to look ahead and read just enough.

It isn't demonstrated in this tutorial, but you can use readline to read a line at a time, again using eof to look ahead.
[slitt@mydesk slitt]$ ./hello.rb
s!arch domain.cxm
nam!s!rv!r 192.168.100.103
nam!s!rv!r 209.63.57.200

# ppp t!mp !ntry
[slitt@mydesk slitt]$

How OOP is Ruby?
You hear it all the time. "Ruby's a purely Object Oriented language!"

On some levels that's a true statement, but it's misleading. It misled me into staying away from Ruby for three years.

See, to me "purely OOP" means a language you can't write procedural code with. Java, for instance, where you need to create a class to write a "hello world" program, and you can't make a subroutine outside of a class.

Ruby's not like that. A Ruby "hello world" program is two lines, you can write subroutines outside of any class that are accessible anywhere, and if you'd like you can write complete and complex programs without creating a single class or object.

In Ruby's case, what they mean by "purely OOP" is that all variables are objects. Integers, floating point numbers, characters, strings, arrays, hashes, files -- they're all objects. You manipulate these objects with their methods, not with Ruby built in operators. For instance, in the following:
profit = revenue - expense
In the preceding, profit, revenue and expense are all objects of class Float. The minus sign (-) is not a Ruby operator -- it's a method of the Float class. In the C language, the minus sign would be an operator supplied by the language, but in Ruby it's just a method of the Float class. Incidentally, a plus sign method is implemented in class Fixnum integers, where once again it adds the value, and in the String class, where it concatinates strings.

So Ruby's "purely OOP" in that when you use it you'll definitely be using objects, but you do not need to create objects to write a substantial Ruby programmer. So if you do not consider yourself an Object Oriented programmer, or even if you hate OOP, don't let that stop you from using Ruby.

No comments:

Post a Comment