Introduction to Ruby
"A Programmer's Best Friend"
Ruby
Creator: Yukihiro Matsumoto
Introduced: 1995
Open source
Installable package on many UNIX/Linux systems
-
-
Can be used for tasks that other dynamic programming languages are used for.
Initially gained a following due to the popularity of the
Ruby on Rails web application framework.
-
Popularity/Usage (Stack Overflow Developer Survey)
Ruby Online Resources
Ruby Execution
Programs typically given .rb extension
Executed with ruby prog.rb
Or use shell script type line at top of Ruby script
Interactive shell by running irb
Ruby: Syntax summary
Ruby: What might be familiar
print
and puts
print omits \n at end
puts includes \n at end
Regular expressions
mypattern = %r|[aeiou]|
puts "String has vowels" if "This is a test" =~ /[aeiou]/
puts "String has vowels" if "This is a test".match("[aeiou]")
puts "String has vowels" if "This is a test".match( mypattern )
x = "This is a test".match(/(\w+) (\w+)/)
puts x[0]
puts x[1]
puts x[2]
puts "foobar".sub('bar', 'foo')
puts "this is a test".gsub('i', '')
x = "This is a test"
puts x.sub(/^../, 'Hello')
Also see the Ruby string class'
.scan() method.
Arrays and hashes
x = [1, 2, 3, 4] # array called x
x << 5 # adds 5 to array x
x = { "a" => 1, "b" => 2 } # hash called x
# Ruby-style iteration through hash:
x.each { |key, value| puts "#{key} equals #{value}" }
# The above uses a shorter version of the following 'do' block:
x.each do |key, value|
puts "#{key} equals #{value}"
end
Ruby: What might not be familiar
Control structures
if bool-expr [then]
body
elsif bool-expr [then]
body
else
body
end
while bool-expr [do]
body
end
for name[, name]... in expr [do]
body
end
Variable interpolation
x = 10
y = 20
z = "annoying"
puts "#{x} + #{y} = #{x + y}"
puts "This is so #{z.upcase}!"
# also works # puts "This is so " + z.upcase + "!"
Multi-line strings
x = %q{This is a test
of the multi
line capabilities}
s = 'another'
x = %Q{This is #{s} test
of the multi
line capabilities}
Ruby naming conventions
mystring = "Are strings mutable?"
mystring.downcase
puts mystring + " No."
mystring.downcase!
puts "#{mystring} It Depends!"
Everything except nil and false considered true
# in Ruby, 0 is considered true.
if 0
puts "0 is true"
else
puts "0 is false"
end
Ruby-style iteration and blocks
# Preferred form
some_list.each do |this_item|
# some statements
end
# In Python: for this_item in some_list:
# In Perl: foreach $this_item (some_list)
some_list.each do |this_item|
# some statements
end
some_list.each { |this_item| # some statements } # Example of an inline block
some_list.each.with_index do |item, item_index|
# Sample statement to print numbered list of items:
puts "#{item_index}. #{item}"
end
# Can also specify starting value of item_index:
some_list.each.with_index(1) do |item, item_index|
# Sample statement to print numbered list of items:
puts "#{item_index}. #{item}"
end
Functional ops using map and filter
In the functional programming paradigm, the “map” and “filter” operations are important “
higher-order” functions for processing collections of data.
Ruby does not have
list comprehensions like Python, but methods like
map
and
filter
may serve the same purpose as list comprehensions, i.e., create lists from lists.
# Range of ints from 1 to 10
nums = 1..10
# Map applies a block to every element of an array
# and returns a resulting array of the same size:
nums.map do |num|
num.to_s # returns string copy of num
end
# Assign result of map to an array:
strnums = nums.map do |num|
num.to_s
end
# Map an inline block and replace original Range object with an array:
nums = nums.map { |num| num.to_s }
# Replace original array contents with map!:
nums.map! { |num| num.to_i }
# Array of symbols:
animals = [:mouse, :bat, :pangolin]
# Map with array index included (index starts at 1):
animals.map.with_index(1) { |name, index| "#{index}. #{name}" }
# What is returned when a void function block is mapped?
animals.map.with_index(1) { |name, index| puts "#{index}. #{name}" }
# Use %w percent string to create a list of strings:
words = %w{You feel a whole lot more like you do
now than you did when you used to}
# Filter words in array that have length <= 3:
words.filter do |word|
word.length <= 3 # boolean block
end
# Shorter filter that modifies original words array:
words.filter! { |word| word.length <= 3 }
Symbols
Symbols, a feature of languages such as LISP
begin with :
don't contain values or objects, unlike variables
can be considered literal constants that have no value
current_situation = :good
puts "Everything is fine" if current_situation == :good
puts "PANIC!" if current_situation == :bad
# as opposed to
current_situation = "good"
puts "Everything is fine" if current_situation == "good"
puts "PANIC!" if current_situation == "bad"
person1 = { :name => "Fred", :age => 20, :gender => :male }
person1 = { :name => "Laura", :age => 23, :gender => :female }
Ruby methods (functions)
def say_hello( name )
"Hello, " + name # Same as: return "Hello, " + name
end
puts say_hello "Chris" # Same as: puts say_hello( "Chris" )
Ruby Classes and Objects
Discovering classes and methods
a = "This is a test"
puts a.class
a = "This is a test"
puts a.methods.sort.join(' ')
Classes
class Person
attr_accessor :name, :age, :gender
# note use of symbols
end
person_instance = Person.new
person_instance.name = "Robert"
person_instance.age = 52
person_instance.gender = "male"
puts person_instance.name
Intro to class inheritance in Ruby
class Pet
attr_accessor :name, :age, :gender, :color
end
class Cat < Pet
end
class Dog < Pet
# Dog-specific method
def bark
puts "Woof!"
end
end
class Snake < Pet
attr_accessor :length
# additional attribute for Snake
end
Using instance or object variables (@varname)
# base class Shape
class Shape
end
class Square < Shape
# consider initialize method to be the "constructor"
def initialize( side_length )
@side_length = side_length
end
# Instance variables are private by default, so
# @side_length is private unless made public with
# attr_accessor :side_length
# Methods are public unless declared private:
def area
@side_length * @side_length
end
def perimeter
@side_length * 4
end
end
class Triangle < Shape
def initialize( base_width, height, side1, side2, side3 )
@base_width = base_width
@height = height
@side1 = side1
@side2 = side2
@side3 = side3
end
def area
@base_width * @height / 2
end
def perimeter
@side1 + @side2 + @side3
end
end
my_square = Square.new( 5 )
my_triangle = Triangle.new( 6, 6, 7.81, 7.81, 7.81 )
puts my_square.area
puts my_square.perimeter
puts my_triangle.area
puts my_triangle.perimeter
# Attempt to change @side_length of my_square:
my_square.side_length = 10 # will fail without an attr_accessor for :side_length
puts my_square.area
puts my_square.perimeter
Using class variables (@@varname)
class Square
def initialize
if defined?( @@number_of_squares )
@@number_of_squares += 1
else
@@number_of_squares = 1
end
end
# A class method begins with the name of the class itself
def Square.count
@@number_of_squares
# "return" is optional
end
end
a = Square.new
puts Square.count
b = Square.new
puts Square.count
Rubygems: Ruby packaging system
# List all available gems; hit q to quit the more pager
gem list --remote | more
# Download and install gems
gem install nokogiri open-uri sqlite3
Ruby and databases
SQLite with Ruby
SQLite is a lightweight SQL database that does not require a DB server running in the background.
Widely-adopted for configuration management, e.g. Firefox, Chrome and related browsers store user profiles, browsing history, etc. in SQLite databases.
Example: Menu-driven program that allows you to create, manipulate and search a database table.
-
You need to have the sqlite3
gem installed. If you successfully installed the rails
gem, you have the sqlite3
gem.
After you finish running rbdb2.rb
, you will have a dbfile
in the same directory as the Ruby program.
Ruby on Rails: An introduction
Ruby on Rails (RoR or Rails) is an open source Web application development framework.
Goal: Make it possible to develop Web applications in an easy, straightforward manner, with as few lines of code as necessary.
For this to be possible, Rails makes assumptions and uses default configurations that work for most Web apps.
The attraction of Rails is that it removes much of the groundwork needed to develop Web apps.
Features such as database access, dynamic page elements (
using JavaScript), templating and data validation are either preconfigured or take only a few lines of code to configure.
Rails & the Model-View-Controller architecture
-
A complete production-level Rails system requires Ruby, the Rails framework (the 'rails' and other Rubygems), a Web server such as Apache or nginx, a database such as MySQL or sqlite, Node.js, and more.
-
Sample app - mydiary