Intro to Ruby
Follow Along
http://j.mp/nicar-13-ruby
Schedule
1. Set up the room
2. Variables, types, conditional, iteration
3. Methods and classes
4. RubyGems, APIs, Scraping
Set up the room.
$ irb
irb(main):001:0> puts "hello"
hello
=> nil
Intro.
Programming is 3 things
Assignment, Conditional, Iteration
Assignment
Conditional
if name == "Al"
puts "Hello #{name}"
end
Iteration
names = ["Al", "Joe", "Sally"]
names.each do |name|
puts "#{name} is here!"
end
Let's go!
Strings & Integers
address = 55
street = "Broadway"
city = "New York"
state = "NY"
zip_code = "10003"
city + ", " + state
#=> "New York, NY"
"#{city}, #{state}"
#=> "New York, NY"
"#{address} #{street}"
#=> "55 Broadway"
address + " " + street
#=> TypeError: String can't be coerced into Fixnum
from (irb):10:in `+'
from (irb):10
address.to_s + " " + street
#=> "55 Broadway"
Type coercion
5.to_s #=> "5"
"5".to_i #=> 5
5.to_f #=> 5.0
str = ""
str << city
str << ", "
str << state
#=> "New York, NY"
str = ""
str += city
str += ", "
str += state
#=> "New York, NY"
address += address
#=> 110
a = 3
b = 3
a == b
#=> true
a = 3
b = 3
if a == b
puts 'they match'
end
a = 1
b = 2
if a != b
puts "They don't match!"
end
a = 3
b = 3
if a == b
puts "they match"
else
puts "they don't match"
end
Arrays & Hashes
students = ["Amy", "Joe", "Sally", "Harry"]
students.pop
#=> "Harry"
students
#=> ["Amy", "Joe", "Sally"]
students.shift
#=> "Amy"
students
#=> ["Joe", "Sally"]
students << "Amy"
#=> ["Joe", "Sally", "Amy"]
person = {}
person[:first_name] = "Al"
person[:last_name] = "Shaw"
person = {
:first_name => "Al",
:last_name => "Shaw"
}
person[:first_name]
#=> "Al"
people = []
people.push(person)
#=> [{:first_name=>"Al", :last_name=>"Shaw"}]
Iteration
students.each do |student|
puts "#{student} is in class today"
end
#=>
Joe is in class today
Sally is in class today
Amy is in class today
even_numbers = [2, 4, 6, 8, 10]
odd_numbers = []
# how can we programmatically
# fill up this array with odd numbers
even_numbers.each do |n|
odd_numbers << n + 1
end
odd_numbers
#=> [2, 4, 6, 8, 10]
even_numbers.map do |n|
n + 1
end
#=> [3, 5, 7, 9, 11]
even_numbers.map { |n| n + 1 }
#=> [3, 5, 7, 9, 11]
even_numbers
#=> [2, 4, 6, 8, 10]
even_numbers.map! { |n| n + 1 }
#=> [3, 5, 7, 9, 11]
Methods
# Who's in class today?
def is_in_class(student)
attendance = {
"Amy" => true,
"Joe" => true,
"Sally" => false,
"Harry" => true
}
if attendance[student]
puts "here"
else
puts "absent"
end
end
# Try it
is_in_class("Sally")
#=> Absent
is_in_class("Joe")
#=> Here
Classes are factories for objects
class Student
attr_reader :name, :grade
def initialize(name, grade)
@name = name
@grade = grade
end
end
s = Student.new("Sally", 8)
#=> #<Student:0x1052aca28 @name="Sally", @grade=8>
s.name
#=> "Sally"
Why should I care?
Let's build a system that assigns students to teachers!
class Student
attr_reader :name, :grade, :teacher
def initialize(name, grade)
@name = name
@grade = grade
end
@@teachers = {
"Shanahan" => 5,
"Kovacek" => 5,
"Streich" => 5,
"Ankunding" => 5,
"Marks" => 5
}
def assign_teacher
@@teachers.each do |t_name, slots|
if slots > 0
@teacher = t_name
@@teachers[t_name] -= 1
puts "#{@name} is assigned to #{t_name}"
puts "#{t_name} now has #{slots - 1} slots left"
return
end
end
end
end
s = Student.new("Sally", 8)
#=> #<Student:0x1052aca28 @name="Sally", @grade=8>
s.assign_teacher
Sally is assigned to Streich
Streich now has 4 slots left
s.teacher
#=> "Streich"
Everything in Ruby is an object
class Fixnum
def +(num)
self - num
end
end
I just blew your mind
A useful example:
[1,2,3].sum
NoMethodError: undefined method `sum' for [1, 2, 3]:Array
from (irb):1
class Array
def sum
self.reduce(0) {|memo, it| memo += it; memo}
end
end
RubyGems are bits of code that add functionality to Ruby
require 'rubygems'
require 'json'
Let's use the JSON gem to play with the Facebook API
require 'rubygems'
require 'json'
require 'open-uri'
JSON.parse(open("http://graph.facebook.com/ashaw").read)
{"gender"=>"male",
"id"=>"2902652",
"locale"=>"en_US",
"username"=>"ashaw",
"first_name"=>"Al",
"last_name"=>"Shaw",
"name"=>"Al Shaw",
"link"=>"http://www.facebook.com/ashaw"}
Finally, let's use Nokogiri to do some simple scraping
require 'rubygems'
require 'nokogiri'
require 'open-uri'
FEC.gov
url = "http://query.nictusa.com/cgi-bin/dcdev/forms/ \
C00490045/766953/sa/11AI"
doc = Nokogiri::HTML(open(url).read)
names = []
donors = doc.css("table tr td[align=LEFT]")
donors.each do |donor|
name = donor.css("b")[0].content
names << name
end
names
#=>
["Marc Andreessen",
"Michael Armstrong",
"Alan Ashton",
"Lynda Balfour",
"Frank Baxter",
"Glen Beck",
"James Berardinelli",
...
]
Thank you. Questions?
Al Shaw NICAR 2013 @A_L