This page provides a brief demonstration of the Ruby programming language presented at the St. John's Linux Users' Group on February 12, 2008. The demo used Ruby v1.8.6. It is not intended to be a comprehensive overview of all features of the language. This presentation was eventually broken into two parts. This initial presentation dealt primarily with the Ruby programming language. Part II discussed the Ruby on Rails web application framework.
(A previous presentation on Ruby was prepared a few years ago, but is a bit dated now.)
Ruby and Ruby on Rails can be installed on most Linux systems using conventional package management software (rpm, apt-get, synaptic, etc.). Unfortunately, some of these packages (especially the packages associated with Rails) may be out dated.
This script will download and install ruby version 1.8.6 and rails version 2.0.2 in the "local/" subdirectory of the directory in which is it run. Rails is installed by the RubyGems package manager. (Note: The ftp.ruby-lang.org server is a bit slow. You can download ruby-1.8.6-p111.tar.gz from here instead.) The installation script assumes that wget and various database and development tools and libraries are present on your system (e.g., gcc, sqlite3, zlib1g-dev, libssl-dev, libsqlite3-dev, etc.) are already installed on your system.
To subsequently use Ruby and Ruby on Rails, you must update/set your PATH and RUBYLIB environment variables by running the short script generated by the above installation script. On some gentoo systems, it may also be necessary to unset the RUBYOPT variable.
Most of these examples can be performed in the interactive ruby environment. Type irb at the command prompt to enter this environment. Many of these examples were explained during the presentation.
$ irb irb(main):001:0> puts "Hello world!" Hello world => nil
The nil is the return result of puts.
irb(main):002:0> a = 1 => 1 irb(main):003:0> b = 2 => 2 irb(main):004:0> a + b => 3 irb(main):005:0> a = "Hello" => Hello
irb(main):006:0> a.size => 5 irb(main):007:0> b.class => Fixnum irb(main):008:0> a.class => String irb(main):009:0> -2.abs => 2 irb(main):010:0> "Hello".size => 5
Note that methods can be invoked on variables and literals/constants.
irb(main):011:0> a + " World!" => Hello World! irb(main):012:0> a + b TypeError: can't convert Fixnum into String from (irb):10:in `+' from (irb):10 from :0 irb(main):013:0> a.to_i + b => 2 irb(main):014:0> a + b.to_s => "Hello2" irb(main):015:0> b.to_s + " World!" => "2 World!" irb(main):016:0> b + " World!".to_i => 2
Type conversions are not automatic, generally.
Ruby expressions enclosed by #{...} inside double quotes are evaluated and converted to strings.
irb(main):017:0> "#{b} World!" => "2 World!" irb(main):018:0> "Super Mario #{b ** 6}" => "Super Mario 64"
irb(main):019:0> a = ["Hello", 2, "world", [1, "abc"]] => ["Hello", 2, "world", [1, "abc"]] irb(main):020:0> a[2] => "world" irb(main):021:0> a[0] => "Hello" irb(main):022:0> a[-1] => [1, "abc"] irb(main):023:0> a[-1][-1] => "abc" irb(main):024:0> a.first == a[0] && a.last == a[-1] => true irb(main):025:0> a[10] => nil irb(main):026:0> a[10] = "final" => "final" irb(main):027:0> a => ["Hello", 2, "world", [1, "abc"], nil, nil, nil, nil, nil, nil, "final"] irb(main):028:0> a << "new-final" => ["Hello", 2, "world", [1, "abc"], nil, nil, nil, nil, nil, nil, "final", "new-final"] irb(main):029:0> a.pop => "new-final" irb(main):030:0> a.shift => "Hello" irb(main):031:0> a => [2, "world", [1, "abc"], nil, nil, nil, nil, nil, nil, "final"] irb(main):032:0> a.join("-") => "2-world-1-abc-------final" irb(main):033:0> words = "hello world this is a string".split => ["hello", "world", "this", "is", "a", "string"] irb(main):034:0> words.include?("this") => true
irb(main):035:0> h = { "NL" => "St. John's", "NS" => "Halifax" } => {"NS"=>"Halifax", "NL"=>"St. John's"} irb(main):036:0> h.has_key?("NL") => true irb(main):037:0> h["NL"] => "St. John's" irb(main):038:0> h["NB"] = "Fredericton" => "Fredericton" irb(main):039:0> h => {"NS"=>"Halifax", "NL"=>"St. John's", "NB"=>"Fredericton"} irb(main):040:0> h.keys => ["NS", "NL", "NB"] irb(main):041:0> h.value => ["Halifax", "St. John's", "Fredericton"]
irb(main):042:0> :hello => :hello irb(main):043:0> :hello.to_s => "hello" irb(main):044:0> "sym".intern => :sym irb(main):045:0> font = {:size => "10pt", :weight => "bold"} => {:weight=>"bold", :size=>"10pt"} irb(main):046:0> font[:weight] => "bold"
Using symbols as keys in a hash is very common in Ruby (especially in Rails).
Symbols can also be used as crude enumerated types (e.g., COLORS = [:red, :green, :blue]) or "function pointers":
irb(main):047:0> fp = :puts => :puts irb(main):048:0> send(fp, "Hi There!") Hi There! => nil
irb(main):049:0> valid_input = 100..200 => 100..200 irb(main):050:0> valid_input === 150 => true irb(main):051:0> valid_input === 50 => false irb(main):052:0> alphabet = ('A'..'Z').to_a ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"] irb(main):053:0> alphabet[10..-10] => ["K", "L", "M", "N", "O", "P", "Q"]
irb(main):054:0> 5.times { puts "Hello world" } Hello world Hello world Hello world Hello world Hello world => 5 irb(main):055:0> 100.times { |x| puts "%2d" % x } 0 1 2 ... 98 99 => 100 irb(main):056:0> a = ["hello", 2, "world"] => ["hello", 2, "world"] irb(main):057:0> a.each {|element| puts element } hello 2 world => ["hello", 2, "world"] irb(main):058:0> a.each_with_index {|e, idx| puts "(%d) %s" % [idx+1, e] } (1) hello (2) 2 (3) world => ["hello", 2, "world"] irb(main):059:0> for i in a irb(main):059:1> puts i irb(main):059:2> end hello 2 world => ["hello", 2, "world"] irb(main):060:0> font = {:size => "10pt", :weight => "bold"} => {:weight=>"bold", :size=>"10pt"} irb(main):061:0> font.each {|k, v| puts "#{k} is #{v}" } weight is bold size is 10pt => {:weight=>"bold", :size=>"10pt"} irb(main):062:0> (5..10).each { |x| puts "=" * x } ===== ====== ======= ======== ========= ========== => 5..10
The gets method is used to perform line input. The p method is similar to puts, except that it provides a 'lower-level' or verbose (but still human readable) output. By default, chomp will remove the terminating carriage return/newline characters from a string (which is usually present on strings obtained via gets). splitting a string using an empty string delimiter will break the string into a list of all of its characters.
irb(main):063:0> while line = gets irb(main):063:1> p line.chomp.split("") irb(main):063:2> end Hello world! ["H", "e", "l", "l", "o", " ", "w", "o", "r", "l", "d", "!"] a test string ["a", " ", "t", "e", "s", "t", " ", "s", "t", "r", "i", "n", "g"] Ctrl-D => nil
irb(main):064:0> (1..1000).find_all { |x| x % 7 == 0 && x % 13 == 0 } => [91, 182, 273, 364, 455, 546, 637, 728, 819, 910] irb(main):065:0> (1..10).map { |x| x * x } => [1, 4, 9, 16, 25, 36, 49, 64, 81, 100] irb(main):066:0> animals = ["elk", "bear", "aardvark", "dog", "cat"] => ["elk", "bear", "aardvark", "dog", "cat"] irb(main):067:0> animals.sort => ["aardvark", "bear", "cat", "dog", "elk"] irb(main):068:0> animals.sort_by { |a| a.length } => ["elk", "dog", "cat", "bear", "aardvark"] irb(main):069:0> animals.sort_by { |a| [a.length, a] } => ["cat", "dog", "elk", "bear", "aardvark"] irb(main):070:0> (1..20).sort_by { rand } => [19, 9, 18, 2, 7, 11, 16, 5, 10, 12, 3, 8, 15, 14, 17, 6, 1, 13, 20, 4] irb(main):071:0> random_numbers = (1..10).map {rand(100)} => [80, 7, 77, 4, 46, 98, 85, 37, 90, 79] irb(main):072:0> random_numbers.all? { |x| x < 95 } => false irb(main):073:0> random_numbers.any? { |x| x < 10 } => true irb(main):074:0> sum = 0; random_numbers.inject(0) {|sum, n| sum + n} => 603 irb(main):075:0> while line = gets irb(main):075:1> puts line.chomp.split("").sort_by{rand}.join("") irb(main):075:2> end Hello world! llor!o Hlewd What the.... .a.. e.hhtWt ooooooops! oooo!spooo Ctrl-D => nil
These scripts are a little longer. They can be stored in a file and executed using: ruby filename.rb
if 1 > 2 puts "Ruby is lame!" else puts "Okay!" end
words = %w(this is a string) # same as: words = ["this", "is", "a", "string"] if words.include?("this") puts "\"this\" is in the list" fi
Unlike other languages, zero is true — the only false values are false and nil (also note that then is required only when the if statement is all on one line.):
if 0 then puts "zero is true!" else puts "zero is false" end # outputs "zero is true!"
The ternary operator ? : is also supported:
puts 0 ? "zero is true!" : "zero is false"
The traditional case statement is also supported to express more conditional.
print "Birth year> " status = case gets.to_i when 1950..1978 then "old." when 1979..1990 then "not old." when 1991..2008 then "n00b." else "not dead yet?!" end puts "You are #{status}"
$ cat re.rb
html =<<END
<html>
<head>
<title>
Here is the Title
</title>
<body>
<p>
Paragraph One
</p>
<p>
Paragraph Two
</p>
</body>
</html>
END
md = /<title>(.*?)<\/title>/m.match(html)
puts "Title: #{md[1]}"
puts "Tags:"
html.scan(/<.*?>/) { |tag|
puts "\t#{tag}"
}
puts "Detagged:"
puts html.gsub(/<.*?>\s*/, "")
Output:
$ ruby re.rb
Title:
Here is the Title
Tags:
<html>
<head>
<title>
</title>
<body>
<p>
</p>
<p>
</p>
</body>
</html>
Detagged:
Here is the Title
Paragraph One
Paragraph Two
$ cat wx.rb
require 'rss/2.0'
require 'open-uri'
WX_RSS = 'http://www.weatheroffice.gc.ca/rss/city/nf-24_e.xml'
content = ""
open(WX_RSS) { |s| content = s.read }
rss = RSS::Parser.parse(content, false)
# The current conditions item may not be at items[1]
# if there is more than one weather warning. Use 'find'
# to identify where in the items array the "Current
# Conditions" item is located.
current = rss.items.find { |i|
/^Current Conditions:/.match(i.title)
}
location = current.description.split("\n").first
location_detagged = location.gsub(/\s*<.*?>/, "")
puts location_detagged
puts "~" * location_detagged.size
rss.items.each { |item|
puts "- #{item.title}"
}
Output:
$ ruby wx.rb
Observed at: St. John's Int'l Airport 7:30 PM NST Monday 11 February 2008
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- No watches or warnings in effect, St. John's
- Current Conditions: Light Snow, -3.3°C
- Monday night: Flurries. Low minus 4.
- Tuesday: Flurries. High minus 2.
- Tuesday night: Cloudy periods. Low minus 8.
- Wednesday: A mix of sun and cloud. High minus 4.
- Thursday: Snow or rain. Low minus 6. High plus 3.
- Friday: Cloudy. Low minus 5. High plus 2.
Another output sample with weather warnings:
$ ruby wx.rb
Observed at: St. John's Int'l Airport 11:30 AM NST Thursday 14 February 2008
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- RAINFALL WARNING CONTINUED, St. John's
- WIND WARNING, St. John's
- Current Conditions: Light Rain, 1.3°C
- Thursday: Rain at times heavy. High plus 4.
- Thursday night: Rain or drizzle. Low plus 1.
- Friday: Chance of drizzle. Temperature falling to minus 1 by noon. POP 40%
- Saturday: Chance of rain showers or flurries. Low minus 3. High plus 2. POP 60%
- Sunday: A mix of sun and cloud. Low minus 10. High minus 6.
- Monday: A mix of sun and cloud. Low minus 14. High minus 7.
$ cat wb.rb
require 'open-uri'
def get_page(url, opts = {})
html = ""
open(url) { |s| html = s.read }
html = html.gsub(/’/, "'").gsub(/©/, "(c)")
html.gsub!(/<.*?>/m, "") if opts[:detag]
html.gsub!(/(^[ \t]*\n)+/, "\n") if opts[:compress_newlines]
html
end
raise "Usage: #{$0} <URL>" unless ARGV.size == 1
puts get_page(ARGV[0], :detag => true, :compress_newlines => true)
gsub! modifies the given string, destroying its old value (hence the exclamation mark). The return value of the method is the value of the last statement (the return is implicit, but can be used if desired).
Output:
$ ruby wb.rb http://www.slug.nf.net
SLUG - St. John's Linux Users' Group
St.
John's Linux Users' Group
What is SLUG?
SLUG is a
Linux users group based in
St. John's,
Newfoundland,
Canada. We began
in 1994 and are constantly looking to expand our membership
base.
Each term we hold regular public informational seminars on
Linux in the Engineering building
at the Memorial University of
Newfoundland campus, with the support of the
Department of Computer Science.
Announcements
Ruby On Rails
Date: February 12th, 2008
Time: 7:30pm
Location: Memorial University, S.J. Carew Building, Room EN-2022
Presenter: Donald Craig (donald at cs dot mun dot ca)
Ruby on Rails is an multi-platform, open source web application framework
based upon the Model Controller View (MVC) architecture. Its adherence to
principles such as Don't Repeat Yourself (DRY), convention over configuration,
testing, and, more recently, database migrations and RESTful interfaces has
made the framework increasingly popular over the past few years. This talk
will present an brief introduction to Ruby and the Ruby on Rails framework.
Some of the topics to be discussed include: ">
- Installing Ruby on Rails on Linux
- Overview of Ruby.
- Creating a Rails application.
- Scaffolding/Migrations
- ActiveRecord (Models)
- Object Relational Mapping.
- Associations/Relationships
- ActionPack (Controller/Views)
Home
Mailing List
Sign Up
Archives
Events / Seminars
Upcoming
Past
Robocode
Keysigning
Resources
Linux Documentation Project
nf.comp.linux
Canadian LUGs
(c) 2005 St. John's Linux Users' Group.
Site design by Geoff Holden.
$ cat cl.rb
module MyModule
class Aclass
attr_reader :aval
def initialize(value)
@aval = value
end
def to_s
"[A:#{@aval}]"
end
self.cm
"This is a class method"
end
end
end
class Bclass < MyModule::Aclass
attr_accessor :bval
def initialize(avalue, bvalue)
super(avalue)
@bval = bvalue
end
def to_s
super + "[B:#{@bval}]"
end
end
a = MyModule::Aclass.new(10)
puts a
p a
# Class methods are invoked without a corresponding object.
puts MyModule::Aclass.cm
puts a.aval
#a.aval = 20 # Error
b = Bclass.new(20, "hello")
puts b
p b
puts b.bval
b.bval = 30 # OK!
puts b.bval
Output:
$ ruby cl.rb
[A:10]
#<MyModule::Aclass:0xb7e6ed3c @aval=10>
This is a class method
10
[A:20][B:hello]
#<Bclass:0xb7e6e2d8 @aval=20, @bval="hello">
hello
30
More information on the core and standard APIs is available at ruby-doc.org
Part II of this presentation was presented on March 25, 2008.