Ann Arbor Java Users' Group Code Examples
Here is a recap of the talk Eric gave at the February 7, 2006 Ann Arbor Java User's Group (AAJUG) meeting.
Some Links to Help You Get Started
The Southeast Michigan Ruby Users' Group has regular meetings. The web site allows you to get on the mailing list and to see a calendar of events.
The official Ruby web site has a lot of information about the Ruby language itself.
The official Ruby on Rails web site is the hub for information on Rails. In addition to having the full API, there are lots of useful how-to's in the associated wiki.
O'Reilly's Rolling with Ruby on Rails contains a brief introduction along with installation instructions.
O'Reilly's book sales charts that compare the volume of various categories of books over two years.
Additional links can be found on the Ruby Web Sites page.
Ruby Code Examples
controls.rb
Demonstrates the central control structures.
# example with cascading-if
age = 12
if age <= 1
puts "infant"
elsif age <= 2
puts "toddler"
elsif age <= 9
puts "child"
elsif age <= 12
puts "young adult"
elsif age <= 19
puts "teenager"
elsif age <= 64
puts "adult"
else
puts "senior"
end
# example with cascading-if returning a value
age_category = if age <= 1
"infant"
elsif age <= 2
"toddler"
elsif age <= 9
"child"
elsif age <= 12
"young adult"
elsif age <= 19
"teenager"
elsif age <= 64
"adult"
else
"senior"
end
# example of if modifier
discount_percent = 15 if items_bought >= 10
# example of case statement
hour_24 = 23
case hour_24
when 1..11 then
hour_12 = hour_24
meridian = "am"
when 12 then
hour_12 = hour_24
meridian = "pm"
when 13..23 then
hour_12 = hour_24 - 12
meridian = "pm"
else # hour_24 must be 0 (just past midnight)
hour_12 = 12
meridian = "am"
end
puts "The time is #{hour_12}:00 #{meridian}."
# example with while pre-test loop
while line = gets
# process line
end
# example with while post-test loop
begin
puts "What is the password?"
password = gets.chomp
end while password != "aajug"
# example with while modifier
min_value = 83165
power_of_2 = 1
power_of_2 *= 2 while power_of_2 < min_value
puts "First power 2 two that is at least #{min_value} is #{power_of_2}."
Circle.java
A simple class written in Java.
public class Circle {
double x, y, radius;
public Circle (double x, double y, double r) {
this.x = x;
this.y = y;
radius = r;
}
public double getRadius() {
return radius;
}
public void setRadius(double newRadius) {
radius = newRadius;
}
public double getArea() {
return Math.PI * radius * radius;
}
public static void main(String[] arguments) {
Circle c1 = new Circle(3, 4, 5);
System.out.println(c1.getArea());
c1.setRadius(8);
System.out.println(c1.getArea());
}
}
Circle.rb
The equivalent class written in Ruby.
class Circle
attr_accessor :radius # creates 2 methods: "radius" and "radius="
def initialize(x, y, r) # acts like a constructor
@x, @y, @radius = x, y, r # multiple assignment
end
def area
Math::PI * @radius ** 2 # "**" is the power operator
end
end
c1 = Circle.new(3, 4, 5) # new instantiates then calls "initialize"
puts c1.area
c1.radius = 8
puts c1.area
blocks.rb
Demonstrates arrays and blocks in Ruby.
# define an array
stooges = ["Larry", "Moe", "Curly"]
# access the array in various ways
puts stooges # produces: Larry Moe Curly
puts stooges[1] # produces: Moe
puts stooges[1..2] # produces: Moe Curly
puts stooges[-1] # produces: Curly
puts stooges[-2..-1] # produces: Moe Curly
# append to the end of an array
stooges << "Shemp"
puts stooges # produces: Larry Moe Curly Shemp
# loop using for
for s in stooges
puts "#{s} is a stooge."
end
# loop using block delineated by braces
stooges.each { |s| puts "#{s} is a stooge." }
# loop using block delineated by do/end
stooges.each do |s|
puts "#{s} is a stooge."
end
# nested blocks example
stooges.each do |s1|
stooges.each do |s2|
puts "#{s1} pokes #{s2}" if s1 != s2
end
end
blocks-loops.rb
Demonstrates some other ways to execute loops in Ruby using blocks.
# Loop a specified number of times
5.times { puts "Hello World!" }
# Loop with a counter going from 1 to 10
1.upto(10) { |i| puts "#{i}. Hello World!" }
# Loop with a counter going from 1 to 100 by 7
1.step(100, 7) { |j| puts "#{j}. Hello World!" }
# Loop from 44 to 55
(44..55).each { |k| puts "#{k}. Hello World!" }
# Read a file of numbers, one per line, and compute the mean average
count, sum = 0, 0.0
File.open("numbers.txt") do |file|
file.each_line do |line|
count += 1
sum += line.to_f
end
end
puts "Count is #{count}; total is #{sum}; mean average is #{sum / count}."
# Read a file of numbers, one per line, and compute the mean average
count, sum = 0, 0.0
open("numbers.txt") do |file|
file.each_line do |line|
count += 1
sum += line.to_f
end
end
puts "Count is #{count}; total is #{sum}; mean average is #{sum / count}."
hashes.rb
Demonstrates basic operations on a Ruby hash.
# Create a hash providing ireegular plural for various animals
$plurals = { "calf" => "calves", "deer" => "deer",
"fish" => "fish", "fox" => "foxes", "goose" => "geese",
"mouse" => "mice", "octopus" => "octopi", "ox" => "oxen",
"platypus" => "platypuses", "sheep" => "sheep", "wolf" => "wolves"}
# Looking up something in a hash uses array notation
puts $plurals["octopus"]
puts $plurals["ox"]
# Adjusting data in a hash also uses array notation
$plurals["octopus"] = "octopuses" # overwrite mapping
$plurals["hippopotamus"] = "hippopotamuses" # add new mapping
# This method will pluralize an animal using the hash or a standard rule
def pluralize(animal)
irregular_animal = $plurals[animal]
if irregular_animal then return irregular_animal
else return animal + "s"
end
end
# Some example method calls
puts pluralize("dog")
puts pluralize("sheep")
puts pluralize("mouse")
puts pluralize("octopus")
# A block with multiple parameters
$plurals.each_pair do |key, value|
puts "The plural of \"#{key}\" is \"#{value}\""
end
hash-parameters.rb
Demonstrates optional/named parameters through the use of a hash.
class Circle
attr_reader :radius, :circumference, :area
def initialize(hash)
@radius, @circumference, @area =
hash[:radius], hash[:circumference], hash[:area]
if @radius then
@circumference = 2 * Math::PI * @radius
@area = Math::PI * @radius ** 2
elsif @circumference then
@radius = @circumference / (2 * Math::PI)
@area = Math::PI * @radius ** 2
elsif @area then
@radius = Math::sqrt(@area / Math::PI)
@circumference = 2 * Math::PI * @radius
else
@radius, @circumference, @area = 0, 0, 0
end
end
end
c1 = Circle.new(:radius => 5)
c2 = Circle.new(:circumference => 11)
c3 = Circle.new(:area => 25)
puts c1.inspect
puts c2.inspect
puts c3.inspect
def temp_convert(from_temp, hash = {})
from_unit = hash[:from] || :f
to_unit = hash[:to] || :c
fahrenheit = case from_unit
when :f then from_temp
when :c then from_temp * 9.0 / 5.0 + 32
when :k then from_temp * 9.0 / 5.0 - 459.67
else 0
end
to_temp = case to_unit
when :f then fahrenheit
when :c then (fahrenheit - 32) * 5.0 / 9.0
when :k then (fahrenheit + 459.67) * 5.0 / 9.0
else 0
end
to_temp
end
puts temp_convert(32)
puts temp_convert(212)
puts temp_convert(32, :to => :k)
puts temp_convert(0, :from => :c, :to => :f)
puts temp_convert(100, :from => :c, :to => :f)
require 'date'
# Note: does not produce perfect ISO dates, as month and day of month should
# always be two digits, with a leading "0" for values less than 10.
def date_display(date, params = {})
format = params[:format] || :iso
month_format = params[:month] || :numeric
month = date.month
day = date.day
if format == :iso then # guarantee two-digits in iso
month = ("0" + month.to_s)[-2..-1]
day = ("0" + day.to_s)[-2..-1]
end
month = case month_format
when :numeric then month
when :short then Date::ABBR_MONTHNAMES[date.month]
when :long then Date::MONTHNAMES[date.month]
else return "ERROR"
end
case format
when :iso then "#{date.year}-#{month}-#{day}"
when :us then "#{month}/#{day}/#{date.year}"
when :europe then "#{day}/#{month}/#{date.year}"
else "ERROR"
end
end
d1 = Date.civil(2006, 4, 2)
puts date_display(d1)
puts date_display(d1, :month => :short)
puts date_display(d1, :month => :long)
puts date_display(d1, :format => :us)
puts date_display(d1, :format => :europe)
puts date_display(d1, :format => :us, :month => :short)
puts date_display(d1, :month => :really_long)
logging.rb
Demonstrates the power of Duck Typing!
require 'date'
class Logger
def initialize(log)
@log = log
end
# the only operation performed on @log is append (<<)
def add_message(message)
@log << DateTime.now.to_s + ": " + message + "\n"
end
end
# test the logger by putting the entries in an array
array_log = []
logger1 = Logger.new(array_log)
logger1.add_message("test 1")
logger1.add_message("test 2")
logger1.add_message("test 3")
puts array_log
# test the logger by putting the entries in a file
file_log = File.open("log.txt", "w")
logger2 = Logger.new(file_log)
logger2.add_message("test a")
logger2.add_message("test b")
logger2.add_message("test c")
file_log.close
# the magic of Duck Typing!
cubed.rb
Demonstrates that classes are always "open"
# add a cubed method to the Numeric class
# cubed will be inherited by Fixnum, Bignum, and Float
class Numeric
def cubed
self ** 3
end
end
puts 2.cubed
puts 2.2.cubed
puts (2 ** 32).cubed
puts 2.class
puts 2.2.class
puts (2 ** 32).class
ends_with.rb
Demonstrates that classes are always "open"
# add an ends_with method to the String class
class String
def ends_with(ending)
reg_exp = Regexp.new("#{ending}$")
reg_exp.match(self)
end
end
s1 = "Hello World!"
puts "match" if s1.ends_with("!")
puts "match" if s1.ends_with("orld!")
puts "no match" unless s1.ends_with("World")
mix-in.rb
Demonstrates the power of module mix-ins.
# define a Circle class, mix-in the Comparable module, and
# define the <=> operator
class Circle
include Comparable
attr_accessor :radius
def initialize(x, y, r)
@x, @y, @radius = x, y, r
end
def area
Math::PI * @radius ** 2
end
def <=>(other)
return radius <=> other.radius
end
end
# now create two Circles
c1 = Circle.new(3, 4, 5)
c2 = Circle.new(10, 11, 5.2)
c3 = Circle.new(-3, -20, 5)
puts c1 <=> c2
puts c2 <=> c1
puts c1 <=> c3
# now test the six operators defined by the Comparable mix-in
puts "c1 == c2" if c1 == c2
puts "c1 != c2" if c1 != c2
puts "c1 < c2" if c1 < c2
puts "c1 > c2" if c1 > c2
puts "c1 <= c2" if c1 <= c2
puts "c1 >= c2" if c1 >= c2