the well-grounded nuby
DESCRIPTION
Advice on Ruby things to concentrate on as you're learning the language (or helping others learn it), to help you avoid misunderstandings later on.TRANSCRIPT
Copyright © 2010, Ruby Power and Light, LLC
The Well-Grounded Nuby
Advice for Ruby newcomers*
David A. BlackSenior Developer
Cyrus Innovation, Inc.
* and their mentors!
Friday, September 3, 2010
Copyright © 2010, Ruby Power and Light, LLC
About me• Senior Developer at Cyrus Innovation, Inc.
• Rubyist-at-large since 2000 (Pickaxe baby)
• Owner/director of Ruby Power and Light, LLC
• Author of Ruby for Rails (Manning, 2006) and The Well-Grounded Rubyist (Manning, 2009)
• Director of Ruby Central, Inc. (RubyConf, RubyForge, etc.)
• Twitter: @david_a_black, @compleatrubyist
• Ruby learning and history: http://www.ruby-versions.net
Friday, September 3, 2010
Copyright © 2010, Ruby Power and Light, LLC
Goals for today
• Learn some major common points of confusion, and how to navigate them
• Improve your ability to understand Ruby code
• Give yourself some tools for reasoning through code as you write it
Friday, September 3, 2010
Copyright © 2010, Ruby Power and Light, LLC
How we'll proceed
• Seven major points, with code demos
• chosen because they are common stumbling blocks, even among experienced Ruby programmers
• Examples of how the seven points can help you understand Ruby
• Questions (throughout)
Friday, September 3, 2010
Copyright © 2010, Ruby Power and Light, LLC
I.Every expression
evaluates to an object
Friday, September 3, 2010
Copyright © 2010, Ruby Power and Light, LLC
• Everything is not an object
• if statements aren't
• argument lists aren't
• keywords aren't
• But everything evaluates to an object
• including if statements, method definitions, class definitions
Friday, September 3, 2010
Copyright © 2010, Ruby Power and Light, LLC
>> if 3 > 5>> "Not reached!">> end=> nil
>> puts "Hello!"Hello!=> nil
>> class C>> end=> nil
>> class C>> "Some value in a class definition">> end=> "Some value in a class definition"
irb is your friend
Class definitionevaluates to thelast expression insideit
Empty class definitionevaluates to nil
puts returns nil
A failed if statementreturns nil
Friday, September 3, 2010
Copyright © 2010, Ruby Power and Light, LLC
II.It's all about sending messages to objects
Friday, September 3, 2010
Copyright © 2010, Ruby Power and Light, LLC
• Post-dot messages are... messages
• as in "abc".upcase
• Infix and unary operators are (mostly) messages
• Square brackets are a message
• case statements send messages
Messages everywhere...
Friday, September 3, 2010
Copyright © 2010, Ruby Power and Light, LLC
Operators are (mostly) messages (methods)
This... ...is really this!
3 + 2 3.+(2)
5 * 3 5.*(3)
a[2] a.[](2)
+x x.+@(Except you can't actually call the+@ method this way.)
Friday, September 3, 2010
Copyright © 2010, Ruby Power and Light, LLC
Roll your own + logic!class Person attr_accessor :name class Couple def initialize(one, two) @pair = [one, two] end
def to_s @pair[0].name + " and " + @pair[1].name end end
def +(other) Couple.new(self, other) endend
john = Person.newjohn.name = "John"marcia = Person.newmarcia.name = "Marcia"
couple = john + marciaputs couple
Adding two people is definedas returning a Person::Coupleobject with those two people.
John and Marcia
Friday, September 3, 2010
Copyright © 2010, Ruby Power and Light, LLC
Even case statements send messages to objects!
This... ...is really this... ...which is really this!...
case some_stringwhen "abc" # ...when /def/ # ...end
if "abc" === some_string # ...elsif /def/ === some_string # ...end
if "abc".===(some_string) # ...elsif /def/.===(some_string) # ...end
Case statements use the === method,aka the case equality operator, todetermine a match
Friday, September 3, 2010
Copyright © 2010, Ruby Power and Light, LLC
Roll your own ===!class Person attr_accessor :name, :ssn def ===(other) self.ssn == other.ssn endend
david = Person.newdavid.ssn = "123-45-6789"
joe = Person.newjoe.ssn = "987-65-4321"
mystery = david
case mysterywhen joe # i.e., if joe === mystery puts "It's Joe!"when david # i.e., if david === mystery puts "It's David!"end
It's David!
Strictly speaking, youcould just define ==here, since === is thesame as == by default.But defining === itselfmeans that you canseparate "plain" equalityfrom case equality if youwish to.
Friday, September 3, 2010
Copyright © 2010, Ruby Power and Light, LLC
III.Objects resolve
messages into methods
Friday, September 3, 2010
Copyright © 2010, Ruby Power and Light, LLC
• Objects do not "have" methods
• they have the intelligence to find methods when required to do so
• Methods are stored in classes and modules
• Every object has a lookup-path consisting of classes and modules• singleton class• modules mixed into singleton class• class• modules mixed into class• superclass, etc., all the way up
The intelligence of objects
Friday, September 3, 2010
Copyright © 2010, Ruby Power and Light, LLC
from The Well-Grounded Rubyist, © 2009 Manning Publications
Friday, September 3, 2010
Copyright © 2010, Ruby Power and Light, LLC
class Person attr_accessor :nameend
david = Person.newdavid.name = "David"
Friday, September 3, 2010
Copyright © 2010, Ruby Power and Light, LLC
class Person attr_accessor :nameend
david = Person.newdavid.name = "David"
module Vocal def talk "Hi, my name is #{name}." endend
class Person include Vocalend
puts david.talk Hi, my name is David.
Friday, September 3, 2010
Copyright © 2010, Ruby Power and Light, LLC
class Person attr_accessor :nameend
david = Person.newdavid.name = "David"
module Vocal def talk "Hi, my name is #{name}." endend
class Person include Vocalend
puts david.talk
module Loud def talk super.upcase.chomp('.') + "!!!" endend
class Person include Loudend
puts david.talk HI, MY NAME IS DAVID!!!
Friday, September 3, 2010
Copyright © 2010, Ruby Power and Light, LLC
class Person attr_accessor :nameend
david = Person.newdavid.name = "David"
module Vocal def talk "Hi, my name is #{name}." endend
class Person include Vocalend
puts david.talk
module Loud def talk super.upcase.chomp('.') + "!!!" endend
class Person include Loudend
puts david.talk
module Quiet def talk "(((" + super.delete('!').downcase + ".)))" endend
david.extend(Quiet)puts david.talk
(((hi, my name is david.)))
Friday, September 3, 2010
Copyright © 2010, Ruby Power and Light, LLC
IV.Classes and modules
are objects
Friday, September 3, 2010
Copyright © 2010, Ruby Power and Light, LLC
"The answer to 75% of all questions about Ruby is: Because classes are objects!"
-- Me
Friday, September 3, 2010
Copyright © 2010, Ruby Power and Light, LLC
• You can send them messages
• They can be put in arrays, etc.
• They can be assigned to local variables
• They have state (instance variables), just like other objects
• They have some special behaviors (nesting, instantiation, inclusion in lookup path, etc.)
• but in many respects, they are just objects!
Classes and modules as objects
Friday, September 3, 2010
Copyright © 2010, Ruby Power and Light, LLC
Seen in the wild...
def do_something(class_string) THINGS.each do |thing| str = "#{Object.const_get(class_string)}" str << ".#{thing}_method" eval str endend
do_something(an_object.class.name)
Friday, September 3, 2010
Copyright © 2010, Ruby Power and Light, LLC
Don't work so hard!
def do_something(klass) THINGS.each do |thing| klass.send("#{thing}_method") endend
do_something(an_object.class)
Friday, September 3, 2010
Copyright © 2010, Ruby Power and Light, LLC
Classes are objects
class Personend
my_class = Person
david = my_class.new
# class my_class # ERROR!
my_class.class_eval do def speak puts "Hi!" endend
david.speak # Hi!
You can put a class in alocal variable!
You can't use it with theclass keyword. However...
Friday, September 3, 2010
Copyright © 2010, Ruby Power and Light, LLC
V.There's always a self
Friday, September 3, 2010
Copyright © 2010, Ruby Power and Light, LLC
• self is the default receiver of messages
• self owns instance variables• and, by definition, any instance variable you see
belongs to self
• The value of self changes:
• in class definition (becomes the class)• in method definition (to object that will call
method)• in instance_eval (becomes the receiver)
• in class_eval (becomes the class/module)
self-centeredness
Friday, September 3, 2010
Copyright © 2010, Ruby Power and Light, LLC
self
class Person puts "self in the class definition body: #{self}"
def speak puts "Hi! self in the instance method: #{self}" endend
puts "self at the top level: #{self}"
david = Person.newdavid.speak
self in the class definition body: Personself at the top level: mainHi! self in the instance method: #<Person:0x1281bc>
Friday, September 3, 2010
Copyright © 2010, Ruby Power and Light, LLC
self
str = "I am a string!"puts "self is: #{self}"str.instance_eval do puts "self is now: #{self}" puts upcaseend
self is: mainself is now: I am a string!I AM A STRING!
Friday, September 3, 2010
Copyright © 2010, Ruby Power and Light, LLC
self
my_class = Class.newmy_class.class_eval do puts "self in class_eval is: #{self}"end
self in class_eval is: #<Class:0x12857c>
Friday, September 3, 2010
Copyright © 2010, Ruby Power and Light, LLC
VI.Variables contain
references to objects
Friday, September 3, 2010
Copyright © 2010, Ruby Power and Light, LLC
str = "Hi"str2 = strstr2 << " there!"puts str
Hi there!
Friday, September 3, 2010
Copyright © 2010, Ruby Power and Light, LLC
array = [1,2,3]array2 = arrayarray2[3] = 4p array
[1, 2, 3, 4]
Friday, September 3, 2010
Copyright © 2010, Ruby Power and Light, LLC
one = "one"array = [one, "Two", "Three"]one.capitalize!puts onep array
One["One", "Two", "Three"]
Friday, September 3, 2010
Copyright © 2010, Ruby Power and Light, LLC
str = "Hi"str2 = strstr2 += " there"puts str
Hi
+= creates a newstring object!
Friday, September 3, 2010
Copyright © 2010, Ruby Power and Light, LLC
def add_bang(string) string << "!"end
str = "Hi"add_bang(str)puts str
Hi!
Friday, September 3, 2010
Copyright © 2010, Ruby Power and Light, LLC
VII.true and false are objects;
true and false are states
Friday, September 3, 2010
Copyright © 2010, Ruby Power and Light, LLC
Truth and falsehood• Every object has a boolean value
• The objects false and nil have a boolean value of false.
• Every other object has a boolean value of true.
• true is true
• 0 is true
• "" is true
• [] is true
Friday, September 3, 2010
Copyright © 2010, Ruby Power and Light, LLC
The truth testFor any object obj, think of:
if obj puts "obj has a boolean value of true"end
And remember... every expression evaluates to an object, including class definitions!
if class A end puts "True!"end
# No output(because the class definition evaluates to nil)
if class A 0 end puts "True!"end
# Output: True!(because the class definition evaluates to 0,# which has a boolean value of true)
Friday, September 3, 2010
Copyright © 2010, Ruby Power and Light, LLC
SummaryI. Every expression evaluates to an object
II. It's all about sending messages to objects
III. Objects resolve messages into methods
IV. Classes and modules are objects
V. There's always a self
VI. Variables contain references to objects
VII. true and false are objects; true and false are states
Friday, September 3, 2010
Copyright © 2010, Ruby Power and Light, LLC
Questions so far?
Friday, September 3, 2010
Copyright © 2010, Ruby Power and Light, LLC
What do these evaluate to,what do they output,
and why?
Friday, September 3, 2010
Copyright © 2010, Ruby Power and Light, LLC
10 if false
10 if true
puts 10 if true
if 10 > 3 puts "True!"else puts "Not true!"end
if 10 > 3 "True!"end
Friday, September 3, 2010
Copyright © 2010, Ruby Power and Light, LLC
class Talker @x = 1 def talk puts "x is #{@x}" endend
t = Talker.newt.talk
Friday, September 3, 2010
Copyright © 2010, Ruby Power and Light, LLC
class Talker def talk @x = 1 puts "x is #{@x}" endend
t = Talker.newt.talk
Friday, September 3, 2010
Copyright © 2010, Ruby Power and Light, LLC
class C def talk puts "Hi!" endend
Friday, September 3, 2010
Copyright © 2010, Ruby Power and Light, LLC
class C "Hi!"end
Friday, September 3, 2010
Copyright © 2010, Ruby Power and Light, LLC
class C selfend
Friday, September 3, 2010
Copyright © 2010, Ruby Power and Light, LLC
obj = Object.newclass << obj selfend
Friday, September 3, 2010
Copyright © 2010, Ruby Power and Light, LLC
class Person attr_accessor :nameend
d = Person.newd.name = "David"puts d.named.instance_eval { puts name }
Friday, September 3, 2010
Copyright © 2010, Ruby Power and Light, LLC
class Person attr_accessor :nameend
d = Person.newd.name = "David"puts d.named.instance_eval { puts @name }
Friday, September 3, 2010
Copyright © 2010, Ruby Power and Light, LLC
class Person attr_accessor :nameend
d = Person.newd.name = "David"@name = "Matz"puts d.named.instance_eval { puts @name }
Friday, September 3, 2010
Copyright © 2010, Ruby Power and Light, LLC
That's all!
Enjoy your Ruby literacy!
David A. BlackSenior DeveloperCyrus Innovation, Inc.
Friday, September 3, 2010