The Well-Grounded Nuby

54
Copyright © 2010, Ruby Power and Light, LLC The Well-Grounded Nuby Advice for Ruby newcomers* David A. Black Senior Developer Cyrus Innovation, Inc. * and their mentors! Friday, September 3, 2010

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 of The Well-Grounded Nuby

Page 1: The Well-Grounded Nuby

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

Page 2: The Well-Grounded Nuby

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

Page 3: The Well-Grounded Nuby

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

Page 4: The Well-Grounded Nuby

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

Page 5: The Well-Grounded Nuby

Copyright © 2010, Ruby Power and Light, LLC

I.Every expression

evaluates to an object

Friday, September 3, 2010

Page 6: The Well-Grounded Nuby

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

Page 7: The Well-Grounded Nuby

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

Page 8: The Well-Grounded Nuby

Copyright © 2010, Ruby Power and Light, LLC

II.It's all about sending messages to objects

Friday, September 3, 2010

Page 9: The Well-Grounded Nuby

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

Page 10: The Well-Grounded Nuby

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

Page 11: The Well-Grounded Nuby

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

Page 12: The Well-Grounded Nuby

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

Page 13: The Well-Grounded Nuby

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

Page 14: The Well-Grounded Nuby

Copyright © 2010, Ruby Power and Light, LLC

III.Objects resolve

messages into methods

Friday, September 3, 2010

Page 15: The Well-Grounded Nuby

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

Page 16: The Well-Grounded Nuby

Copyright © 2010, Ruby Power and Light, LLC

from The Well-Grounded Rubyist, © 2009 Manning Publications

Friday, September 3, 2010

Page 17: The Well-Grounded Nuby

Copyright © 2010, Ruby Power and Light, LLC

class Person attr_accessor :nameend

david = Person.newdavid.name = "David"

Friday, September 3, 2010

Page 18: The Well-Grounded Nuby

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

Page 19: The Well-Grounded Nuby

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

Page 20: The Well-Grounded Nuby

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

Page 21: The Well-Grounded Nuby

Copyright © 2010, Ruby Power and Light, LLC

IV.Classes and modules

are objects

Friday, September 3, 2010

Page 22: The Well-Grounded Nuby

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

Page 23: The Well-Grounded Nuby

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

Page 24: The Well-Grounded Nuby

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

Page 25: The Well-Grounded Nuby

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

Page 26: The Well-Grounded Nuby

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

Page 27: The Well-Grounded Nuby

Copyright © 2010, Ruby Power and Light, LLC

V.There's always a self

Friday, September 3, 2010

Page 28: The Well-Grounded Nuby

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

Page 29: The Well-Grounded Nuby

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

Page 30: The Well-Grounded Nuby

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

Page 31: The Well-Grounded Nuby

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

Page 32: The Well-Grounded Nuby

Copyright © 2010, Ruby Power and Light, LLC

VI.Variables contain

references to objects

Friday, September 3, 2010

Page 33: The Well-Grounded Nuby

Copyright © 2010, Ruby Power and Light, LLC

str = "Hi"str2 = strstr2 << " there!"puts str

Hi there!

Friday, September 3, 2010

Page 34: The Well-Grounded Nuby

Copyright © 2010, Ruby Power and Light, LLC

array = [1,2,3]array2 = arrayarray2[3] = 4p array

[1, 2, 3, 4]

Friday, September 3, 2010

Page 35: The Well-Grounded Nuby

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

Page 36: The Well-Grounded Nuby

Copyright © 2010, Ruby Power and Light, LLC

str = "Hi"str2 = strstr2 += " there"puts str

Hi

+= creates a newstring object!

Friday, September 3, 2010

Page 37: The Well-Grounded Nuby

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

Page 38: The Well-Grounded Nuby

Copyright © 2010, Ruby Power and Light, LLC

VII.true and false are objects;

true and false are states

Friday, September 3, 2010

Page 39: The Well-Grounded Nuby

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

Page 40: The Well-Grounded Nuby

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

Page 41: The Well-Grounded Nuby

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

Page 42: The Well-Grounded Nuby

Copyright © 2010, Ruby Power and Light, LLC

Questions so far?

Friday, September 3, 2010

Page 43: The Well-Grounded Nuby

Copyright © 2010, Ruby Power and Light, LLC

What do these evaluate to,what do they output,

and why?

Friday, September 3, 2010

Page 44: The Well-Grounded Nuby

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

Page 45: The Well-Grounded Nuby

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

Page 46: The Well-Grounded Nuby

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

Page 47: The Well-Grounded Nuby

Copyright © 2010, Ruby Power and Light, LLC

class C def talk puts "Hi!" endend

Friday, September 3, 2010

Page 48: The Well-Grounded Nuby

Copyright © 2010, Ruby Power and Light, LLC

class C "Hi!"end

Friday, September 3, 2010

Page 49: The Well-Grounded Nuby

Copyright © 2010, Ruby Power and Light, LLC

class C selfend

Friday, September 3, 2010

Page 50: The Well-Grounded Nuby

Copyright © 2010, Ruby Power and Light, LLC

obj = Object.newclass << obj selfend

Friday, September 3, 2010

Page 51: The Well-Grounded Nuby

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

Page 52: The Well-Grounded Nuby

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

Page 53: The Well-Grounded Nuby

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

Page 54: The Well-Grounded Nuby

Copyright © 2010, Ruby Power and Light, LLC

That's all!

Enjoy your Ruby literacy!

David A. BlackSenior DeveloperCyrus Innovation, Inc.

[email protected]

Friday, September 3, 2010