Ruby at NICAR14
← Use arrow keys →
You are here: Intro to Ruby
Coming up:
2. Acquiring & Transforming Data with @thejefflarson
3. Simple Web Apps with @jacqui
Follow Along
http://j.mp/nicar-14-ruby
Part 1 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 = "10006"
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
// In Ruby 2.0, json is installed by default.
// If you don't have it, run
$ gem install json
Let's use the JSON gem to play with the Facebook API
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 '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 2014 @A_L