SlideShare a Scribd company logo
1 of 366
Download to read offline
Meta Programming
     in Ruby
    Steven Soroka
      @ssoroka
self.inspect
self.inspect


•@ssoroka
 on twitter
self.inspect


•@ssoroka
 on twitter

• github.com/ssoroka
self.inspect


•@ssoroka
 on twitter

• github.com/ssoroka
• blog.stevensoroka.ca
self.inspect

• Professionally writing software for 12
  years
• Ruby for 3+ years
• Taught Ruby on Rails at RRC
• My biggest site has over 1 million
  users
What is Ruby?


A dynamic, open source programming language
  with a focus on simplicity and productivity.
            It has an elegant syntax
   that is natural to read and easy to write.


                   http://www.ruby-lang.org
What is Ruby?




      - Yukihiro Matsumoto
What is Ruby?

“Ruby is simple in appearance,
  but is very complex inside”




              - Yukihiro Matsumoto
What is Ruby?

         “Ruby is simple in appearance,
           but is very complex inside”

  “I wanted a scripting language that was more
powerful than Perl, and more object-oriented than
                     Python”

                       - Yukihiro Matsumoto
What is Ruby?
What is Ruby?
• Ruby is not Ruby on Rails
What is Ruby?
• Ruby is not Ruby on Rails
• Ruby is an interpreted language
What is Ruby?
• Ruby is not Ruby on Rails
• Ruby is an interpreted language
 • script language
What is Ruby?
• Ruby is not Ruby on Rails
• Ruby is an interpreted language
 • script language
 • terse
What is Ruby?
• Ruby is not Ruby on Rails
• Ruby is an interpreted language
 • script language
 • terse
 • completely Object Oriented
What is Ruby?
• Ruby is not Ruby on Rails
• Ruby is an interpreted language
  • script language
  • terse
  • completely Object Oriented
• Free, really free.
puts “Hello World”
Meta Programming in Ruby - Code Camp 2010
class Car
class Car
  def start
class Car
  def start
    puts "vroom vroom"
class Car
  def start
    puts "vroom vroom"
  end
class Car
  def start
    puts "vroom vroom"
  end
end
class Car
  def start
    puts "vroom vroom"
  end
end

car = Car.new
class Car
  def start
    puts "vroom vroom"
  end
end

car = Car.new
car.start # vroom
vroom
Does Ruby matter?
Does Ruby matter?
                Rubinious
MacRuby                           JRuby
           Ruby 1.8
                            IronRuby
     Cardinal



                        HotRuby
           IronMonkey
                                  Ruby 1.9
  Ruby Enterprise
      Edition
What Can I do with
     Ruby?
What Can I do with
        Ruby?
• Cross-platform GUI apps (WxRuby,
  FXRuby, Ruby-GNOME2, Ruby Tk)
What Can I do with
        Ruby?
• Cross-platform GUI apps (WxRuby,
  FXRuby, Ruby-GNOME2, Ruby Tk)

• Mac Desktop apps with MacRuby and
  Cocoa
What Can I do with
        Ruby?
• Cross-platform GUI apps (WxRuby,
  FXRuby, Ruby-GNOME2, Ruby Tk)

• Mac Desktop apps with MacRuby and
  Cocoa

• Web Apps (Ruby on Rails, Sinatra)
What Can I do with
        Ruby?
• Cross-platform GUI apps (WxRuby,
  FXRuby, Ruby-GNOME2, Ruby Tk)

• Mac Desktop apps with MacRuby and
  Cocoa

• Web Apps (Ruby on Rails, Sinatra)
• Replace Javascript?
What Can I do with
        Ruby?
• Cross-platform GUI apps (WxRuby,
  FXRuby, Ruby-GNOME2, Ruby Tk)

• Mac Desktop apps with MacRuby and
  Cocoa

• Web Apps (Ruby on Rails, Sinatra)
• Replace Javascript?
• Soon Ruby.NET apps?
WxRuby GUI
WxRuby GUI
Introduction to Ruby
      New Concepts
Differences from C++
Differences from C++

• No type casting
Differences from C++

• No type casting
• There’s only two container types:
  Array and Hash
Differences from C++

• No type casting
• There’s only two container types:
  Array and Hash

• There’s no type conversions, you’ll
  probably find that they aren’t
  necessary
Differences from C++

• No type casting
• There’s only two container types:
  Array and Hash

• There’s no type conversions, you’ll
  probably find that they aren’t
  necessary

• Multithreading is built-in
Differences from C++
Differences from C++

• A unit testing lib comes standard with
  Ruby
Differences from C++

• A unit testing lib comes standard with
  Ruby

• It’s self instead of this
Differences from C++

• A unit testing lib comes standard with
  Ruby

• It’s self instead of this
• Objects are strongly but dynamically
  typed. The runtime discovers at
  runtime if that method call actually
  works
Differences from Java
Differences from Java

• There’s no static type checking.
Differences from Java

• There’s no static type checking.
• Variable names are just labels. They
  don’t have a type associated with
  them
Differences from Java

• There’s no static type checking.
• Variable names are just labels. They
  don’t have a type associated with
  them
• There are no type declarations
Differences from Java

• There’s no static type checking.
• Variable names are just labels. They
  don’t have a type associated with
  them
• There are no type declarations
• foo = Foo.new(“hi”) instead of
  Foo foo = new Foo(“hi”)
Differences from Java

• There’s no static type checking.
• Variable names are just labels. They
  don’t have a type associated with
  them
• There are no type declarations
• foo = Foo.new(“hi”) instead of
  Foo foo = new Foo(“hi”)
Variables
Variables

• Instance variables start with @
Variables

• Instance variables start with @
• Class variables start with @@
Variables

• Instance variables start with @
• Class variables start with @@
• Global variables start with $
Variables

• Instance variables start with @
• Class variables start with @@
• Global variables start with $
• Any type of object can be stored in a
  given variable
Meta Programming in Ruby - Code Camp 2010
a = 5.3
b = 15

a * b # 79.5
Truthiness


• In Ruby, only false and nil are false
• 0 is true
• “” is true
• [] is true
Meta Programming in Ruby - Code Camp 2010
if 0
  puts "0 is truthy"
end

# 0 is truthy
:recipient
deliver_report(:recipient => 'john@example.com')
                 :recipient
Symbols
Symbols

• Symbols are similar to strings, but are
  only allocated memory once, and are
  never freed.
Symbols

• Symbols are similar to strings, but are
  only allocated memory once, and are
  never freed.

• Great for keys, column names, and
  other strings that are repeated over
  and over again.
Meta Programming in Ruby - Code Camp 2010
:name.object_id == :name.object_id
:name.object_id == :name.object_id
# true
:name.object_id == :name.object_id
# true

“name”.object_id == “name”.object_id
:name.object_id == :name.object_id
# true

“name”.object_id == “name”.object_id
# false
Meta Programming in Ruby - Code Camp 2010
john = {
john = {
 :name => 'John Smith',
john = {
 :name => 'John Smith',
 :age => 42
john = {
 :name => 'John Smith',
 :age => 42
}
john = {
 :name => 'John Smith',
 :age => 42
}

john[:name] # 'John Smith'
john = {
 :name => 'John Smith',
 :age => 42
}

john[:name] # 'John Smith'
john[:age] # 42
Interpolation

• Double quoted strings are
  interpolated, single quoted strings are
  not.

   puts “five times three is #{5 * 3}”
   # five times three is 15
   puts ‘five times three is #{5 * 3}’
   # five times three is #{5 * 3}
Everything Has a Value
Everything Has a Value


• Expressions and statements are the
  same thing in Ruby
Everything Has a Value


• Expressions and statements are the
  same thing in Ruby
• Everything returns a value, even if
  that value is nil
Implied Return Values
Implied Return Values
    if 3 > 2
      5
    end

    # returns 5
Implied Return Values
Implied Return Values
    if 2 > 21
      5
    end

    # returns nil
Implied Return Values
Implied Return Values

   pass = if 3.odd?
    ‘odd’
   else
    ‘even’
   end
   # pass == ‘odd’
Classes Are Open
Classes Are Open


• Don’t violate Open/Close Principle
Classes Are Open


• Don’t violate Open/Close Principle
  • OCP says classes should be...
Classes Are Open


• Don’t violate Open/Close Principle
  • OCP says classes should be...
    • open for extension
Classes Are Open


• Don’t violate Open/Close Principle
  • OCP says classes should be...
    • open for extension
    • closed for modification
Classes Are Open
Classes Are Open
 class Float
Classes Are Open
 class Float
   def round
Classes Are Open
 class Float
   def round
     floor
Classes Are Open
 class Float
   def round
     floor
   end
Classes Are Open
 class Float
   def round
     floor
   end
 end
Classes Are Open
 class Float
   def round
     floor
   end
 end
 5.7.round
Classes Are Open
 class Float
   def round
     floor
   end
 end
 5.7.round
 # 5
Classes Are Open
Classes Are Open
class Float
Classes Are Open
class Float
  def round_down
Classes Are Open
class Float
  def round_down
    floor
Classes Are Open
class Float
  def round_down
    floor
  end
Classes Are Open
class Float
  def round_down
    floor
  end
end
Classes Are Open
class Float
  def round_down
    floor
  end
end
5.7.round_down
Classes Are Open
class Float
  def round_down
    floor
  end
end
5.7.round_down
# 5
Everything’s An Object
Everything’s An Object


• properties are called attributes or
  instance variables
Everything’s An Object


• properties are called attributes or
  instance variables

• actions are called methods
String



“I am a string”
‘I am a string’
Fixnum (Integers)
Fixnum (Integers)
42
Fixnum (Integers)
42
42.class # Fixnum
Fixnum (Integers)
42
42.class # Fixnum
42.methods
Fixnum (Integers)
42
42.class # Fixnum
42.methods
# ["&", "*", "**", "+", "-", "/",
Fixnum (Integers)
42
42.class # Fixnum
42.methods
# ["&", "*", "**", "+", "-", "/",
"abs", "between?", "even?",
Fixnum (Integers)
42
42.class # Fixnum
42.methods
# ["&", "*", "**", "+", "-", "/",
"abs", "between?", "even?",
"to_f", "zero?", "|", ...]
Fixnum (Integers)
42
42.class # Fixnum
42.methods
# ["&", "*", "**", "+", "-", "/",
"abs", "between?", "even?",
"to_f", "zero?", "|", ...]
42.odd? # False
Fixnum (Integers)
42
42.class # Fixnum
42.methods
# ["&", "*", "**", "+", "-", "/",
"abs", "between?", "even?",
"to_f", "zero?", "|", ...]
42.odd? # False
42.to_f # 42.0
Float
Float


42.0.class # Float
Float


42.0.class # Float
42.6.floor # 42
Float


42.0.class # Float
42.6.floor # 42
42.6.round # 43
Date (Rails)
Date (Rails)

day = Date.today # Sat, 27 Feb 2010
Date (Rails)

day = Date.today # Sat, 27 Feb 2010
day.tomorrow # Sun, 28 Feb 2010
Date (Rails)

day = Date.today # Sat, 27 Feb 2010
day.tomorrow # Sun, 28 Feb 2010
day.year # 2010
Date (Rails)

day = Date.today # Sat, 27 Feb 2010
day.tomorrow # Sun, 28 Feb 2010
day.year # 2010
day.leap? # false
Date (Rails)

day = Date.today # Sat, 27 Feb 2010
day.tomorrow # Sun, 28 Feb 2010
day.year # 2010
day.leap? # false
42.days.ago # Sat, 16 Jan 2010
Array



my_array = Array.new()
Array



my_array = Array.new()
Array
Array



my_array = []
Array
Array



my_array = [1, 2, 3, 4, 5]
Hash

email_settings = {
  :recipients => 'mom@mom.com',
  :subject => 'hi mom',
  :body => "I'm at CodeCamp!",
  :priority => :normal
}
Hash

email_settings = {
  :recipients => 'mom@mom.com',
  :subject => 'hi mom',
  :body => "I'm at CodeCamp!",
  :priority => :normal
}

send_email(email_settings)
Hash

send_email({
 :recipients => 'mom@mom.com',
 :subject => 'hi mom',
 :body => "I'm at Code Camp!",
 :priority => :normal
})
Hash

send_email(
  :recipients => 'mom@mom.com',
  :subject => 'hi mom',
  :body => "I'm at CodeCamp!",
  :priority => :normal
)
Regular Expressions



    /[aeiou]/
Regular Expressions
Regular Expressions


‘scintillating!’ =~ /[aeiou]/
Regular Expressions


‘scintillating!’ =~ /[aeiou]/
#2
Regular Expressions


‘scintillating!’ =~ /[aeiou]/
#2
Regular Expressions
Regular Expressions


‘scintillating!’.gsub(/[aeiou]/, ‘*’)
Regular Expressions


‘scintillating!’.gsub(/[aeiou]/, ‘*’)
# ‘sc*nt*ll*t*ng!’
Classes

• Single inheritance only
  • but can include functionality from
    modules

• can open a class at any time to add
  methods

• ... are objects!
Methods


• can end in ? or !
• “apples”.is_a?(String)
• Are objects!
Operators are Methods
Operators are Methods
• Most operators are methods
Operators are Methods
• Most operators are methods
 • and can be redefined
Operators are Methods
    • Most operators are methods
       • and can be redefined
class Fixnum
  def +(other)
   self - other
  end
end
Operators are Methods
    • Most operators are methods
       • and can be redefined
class Fixnum
  def +(other)
   self - other
  end
end

5 + 3 # => 2
Blocks

• In Ruby, a block is a namless function
  that can be stored as a callable object,
  called a Proc

• Blocks can be stored in variables
• Blocks can be passed to methods to
  customize their behavior
Meta Programming in Ruby - Code Camp 2010
@users = User.find(:all)
@users = User.find(:all)
@users.each { |user|
@users = User.find(:all)
@users.each { |user|
 user.send_invoice!
@users = User.find(:all)
@users.each { |user|
  user.send_invoice!
}
Meta Programming in Ruby - Code Camp 2010
arr = [5,3,1,5,3,2,6,8,1,2]
arr = [5,3,1,5,3,2,6,8,1,2]

arr.sort{|a,b| a <=> b }
arr = [5,3,1,5,3,2,6,8,1,2]

arr.sort{|a,b| a <=> b }
# [1, 1, 2, 2, 3, 3, 5, 5, 6, 8]
arr = [5,3,1,5,3,2,6,8,1,2]

arr.sort{|a,b| a <=> b }
# [1, 1, 2, 2, 3, 3, 5, 5, 6, 8]

arr.sort{|a,b| b <=> a }
arr = [5,3,1,5,3,2,6,8,1,2]

arr.sort{|a,b| a <=> b }
# [1, 1, 2, 2, 3, 3, 5, 5, 6, 8]

arr.sort{|a,b| b <=> a }
# [8, 6, 5, 5, 3, 3, 2, 2, 1, 1]
Block Objects are
    Closures
Block Objects are
         Closures
• Block Objects (Procs) can be executed
  anywhere and can take their context
  (called binding) with them.
Block Objects are
         Closures
• Block Objects (Procs) can be executed
  anywhere and can take their context
  (called binding) with them.

• A closure is a block of code that, when
  run, is executed within the scope it
  was defined (i.e. local variables are
  available to the block), even after the
  function has returned, and its local
  scope has been destroyed.
Meta Programming in Ruby - Code Camp 2010
user_total = Proc.new {
user_total = Proc.new {
 User.count
user_total = Proc.new {
  User.count
}
user_total = Proc.new {
  User.count
}

user_total.call
user_total = Proc.new {
  User.count
}

user_total.call
# 52
user_total = Proc.new {
  User.count
}

user_total.call
# 52
# user is added
user_total = Proc.new {
  User.count
}

user_total.call
# 52
# user is added
user_total.call
user_total = Proc.new {
  User.count
}

user_total.call
# 52
# user is added
user_total.call
# 53
Array#map
Array#map


[1,2,3,4,5].map{|i| i * 2}
Array#map


[1,2,3,4,5].map{|i| i * 2}
# [2,4,6,8,10]
Array#inject
Array#inject

[1,2,3,4,5].inject(0){|sum, i|
Array#inject

[1,2,3,4,5].inject(0){|sum, i|
  i + sum
Array#inject

[1,2,3,4,5].inject(0){|sum, i|
  i + sum
}
Array#inject

[1,2,3,4,5].inject(0){|sum, i|
  i + sum
}
# 15
Array#inject
Array#inject
class Array
Array#inject
class Array
 def sum
Array#inject
class Array
 def sum
  self.inject(0){|sum, i| i + sum }
Array#inject
class Array
 def sum
  self.inject(0){|sum, i| i + sum }
 end
Array#inject
class Array
 def sum
  self.inject(0){|sum, i| i + sum }
 end
end
Array#inject
class Array
 def sum
  self.inject(0){|sum, i| i + sum }
 end
end

[1,2,3,4,5].sum
Array#inject
class Array
 def sum
  self.inject(0){|sum, i| i + sum }
 end
end

[1,2,3,4,5].sum
# 15
Array#inject
Array#inject

[1,2,3,4,5].inject(0){|best, i|
Array#inject

[1,2,3,4,5].inject(0){|best, i|
  i % 2 == 0 ? i : best
Array#inject

[1,2,3,4,5].inject(0){|best, i|
  i % 2 == 0 ? i : best
}
Array#inject

[1,2,3,4,5].inject(0){|best, i|
  i % 2 == 0 ? i : best
}
#4
Array#select
Array#select

[1,2,3,4,5].select{| i|
Array#select

[1,2,3,4,5].select{| i|
  i % 2 == 0
Array#select

[1,2,3,4,5].select{| i|
  i % 2 == 0
}
Array#select

[1,2,3,4,5].select{| i|
  i % 2 == 0
}
# [2, 4]
Array#reject
Array#reject

[1,2,3,4,5].reject{| i|
Array#reject

[1,2,3,4,5].reject{| i|
  i % 2 == 0
Array#reject

[1,2,3,4,5].reject{| i|
  i % 2 == 0
}
Array#reject

[1,2,3,4,5].reject{| i|
  i % 2 == 0
}
# [1, 3, 5]
Extending Classes
• Make a module
• include it in to a class
Extending Classes
  • Make a module
  • include it in to a class
module Awesomeness
end

class Mundane
  include Awesomeness
end
Meta Programming
Meta programming is writing code that
            writes code
class Car
 def color
  @color
 end

 def color=(color)
   @color = color
 end
 ...
class Car
 def color
  @color

                       class Car
 end

 def color=(color)

                        def color
  @color = color
 end


                         @color
 def engine
  @engine
 end

 def engine=(engine)
  @engine = engine
                        end
 end

 def make
  @make
 end
                        def color=(color)
 def make=(make)
  @make = make
 end                      @color = color
 def model
  @model
 end
                        end
 def model=(model)
  @model = model
                        ...
 end
end
Meta Programming in Ruby - Code Camp 2010
class Car
 attr_accessor :color, :engine, :make, :model
end
class Car
 attr_accessor :color, :engine, :make, :model
end
class Object
class Car
 attr_accessor :color, :engine, :make, :model
end
class Object
 def self.attr_accessor(*attributes)
class Car
 attr_accessor :color, :engine, :make, :model
end
class Object
 def self.attr_accessor(*attributes)
  attributes.each{|attribute|
class Car
 attr_accessor :color, :engine, :make, :model
end
class Object
 def self.attr_accessor(*attributes)
  attributes.each{|attribute|
   # define getter
class Car
 attr_accessor :color, :engine, :make, :model
end
class Object
 def self.attr_accessor(*attributes)
  attributes.each{|attribute|
   # define getter
   define_method(attribute) do
class Car
 attr_accessor :color, :engine, :make, :model
end
class Object
 def self.attr_accessor(*attributes)
  attributes.each{|attribute|
   # define getter
   define_method(attribute) do
    instance_variable_get("@#{attribute}")
class Car
 attr_accessor :color, :engine, :make, :model
end
class Object
 def self.attr_accessor(*attributes)
  attributes.each{|attribute|
   # define getter
   define_method(attribute) do
    instance_variable_get("@#{attribute}")
   end
class Car
 attr_accessor :color, :engine, :make, :model
end
class Object
 def self.attr_accessor(*attributes)
  attributes.each{|attribute|
   # define getter
   define_method(attribute) do
    instance_variable_get("@#{attribute}")
   end
   # define setter
class Car
 attr_accessor :color, :engine, :make, :model
end
class Object
 def self.attr_accessor(*attributes)
  attributes.each{|attribute|
   # define getter
   define_method(attribute) do
    instance_variable_get("@#{attribute}")
   end
   # define setter
   define_method("#{attribute}=") do |var|
class Car
 attr_accessor :color, :engine, :make, :model
end
class Object
 def self.attr_accessor(*attributes)
  attributes.each{|attribute|
   # define getter
   define_method(attribute) do
    instance_variable_get("@#{attribute}")
   end
   # define setter
   define_method("#{attribute}=") do |var|
    instance_variable_set("@#{attribute}", var)
class Car
 attr_accessor :color, :engine, :make, :model
end
class Object
 def self.attr_accessor(*attributes)
  attributes.each{|attribute|
   # define getter
   define_method(attribute) do
    instance_variable_get("@#{attribute}")
   end
   # define setter
   define_method("#{attribute}=") do |var|
    instance_variable_set("@#{attribute}", var)
   end
class Car
 attr_accessor :color, :engine, :make, :model
end
class Object
 def self.attr_accessor(*attributes)
  attributes.each{|attribute|
    # define getter
    define_method(attribute) do
     instance_variable_get("@#{attribute}")
    end
    # define setter
    define_method("#{attribute}=") do |var|
     instance_variable_set("@#{attribute}", var)
    end
  }
class Car
 attr_accessor :color, :engine, :make, :model
end
class Object
 def self.attr_accessor(*attributes)
  attributes.each{|attribute|
    # define getter
    define_method(attribute) do
     instance_variable_get("@#{attribute}")
    end
    # define setter
    define_method("#{attribute}=") do |var|
     instance_variable_set("@#{attribute}", var)
    end
  }
end
Introspection
   self.inspect
.class
.class


• Any object will respond to .class
.class


• Any object will respond to .class
• Car.new.class # Car
.class


• Any object will respond to .class
• Car.new.class # Car
• Car.class # Class
.ancestors


• class BMW < Car
   ...
  end

 • BMW.ancestors # [Car, Object,
    Kernel]
.methods



• Every object responds to .methods
.instance_variable_set



• object.instance_variable_set(“@quantity”, 51)
.instance_variable_get



• object.instance_variable_get(“@quantity”)
  # 25
.instance_variables

• Gem.instance_variables
 # [“@gem_home”, “@ruby”,
 “@gem_path”, ...]
• Gem.instance_variable_get(
 “@gem_home”)
 # [“/Library/Ruby/Gems/1.8”, ...]
.constants
• Math.constants # [“PI”, “E”]
• Math::PI # 3.14159265358979
• Math::E # 2.71828182845905
• Math.const_get(“PI”)
  # 3.14159265358979
• Math.const_set(“GOOGOL”, 10 **
  100)
.respond_to?


• Tells you if objects will respond to a
  certain method.

• ‘string’.respond_to?(:size) # true
.inspect

• Car.new.inspect
  # => "#<Car:0x123d9e8>"

• fish = :tuna
  fish.inspect
  # => ":tuna"
• 5.inspect
  # => "5"
Dynamically Calling
      Methods


• car.respond_to?(:start_engine)
• car.send(:start_engine)
Method Missing



• You can define ghost methods that
  don’t actually exist, but pretend to
  when requested
class Elephant
 def initialize
  @called = []
 end

 def method_missing(method, *args, &block)
  @called << method
 end

 def talk
  puts @called.inspect
 end
end
Meta Programming in Ruby - Code Camp 2010
class Elephant
 # ...
 def method_missing(method, *args, &block)
  @called << method
 end

 def talk # ...
end
class Elephant
 # ...
 def method_missing(method, *args, &block)
  @called << method
 end

 def talk # ...
end
suzie = Elephant.new
class Elephant
 # ...
 def method_missing(method, *args, &block)
  @called << method
 end

 def talk # ...
end
suzie = Elephant.new
suzie.brush
class Elephant
 # ...
 def method_missing(method, *args, &block)
  @called << method
 end

 def talk # ...
end
suzie = Elephant.new
suzie.brush
suzie.do_tricks
class Elephant
 # ...
 def method_missing(method, *args, &block)
  @called << method
 end

 def talk # ...
end
suzie = Elephant.new
suzie.brush
suzie.do_tricks
suzie.ride
class Elephant
 # ...
 def method_missing(method, *args, &block)
  @called << method
 end

 def talk # ...
end
suzie = Elephant.new
suzie.brush
suzie.do_tricks
suzie.ride
suzie.talk # [‘brush’, ‘do_tricks’, ‘ride’]
define_method()

class Html
 def self.tag(tag_name, content)
  "<#{tag_name}>#{content}</#{tag_name}>"
 end
end
class Html
 def self.tag(tag_name, content)
  "<#{tag_name}>#{content}</#{tag_name}>"
 end
end

Html.tag(‘strong’, “I’m strong!”)
# <strong>I’m strong!</strong>
class Html
 def self.tag(tag_name, content)
  "<#{tag_name}>#{content}</#{tag_name}>"
 end

 def self.strong(content)
  tag(‘strong’, content)
 end
end

Html.strong(“I’m strong!”)
# <strong>I’m strong!</strong>
class Html
 TAG_TYPES = [‘strong’, ‘div’, ‘span’, ‘a’, ‘ul’]

 def self.tag(tag_name, content)
  "<#{tag_name}>#{content}</#{tag_name}>"
 end

 def self.strong(content)
  tag(‘strong’, content)
 end
end

Html.strong(“I’m strong!”)
# <strong>I’m strong!</strong>
class Html
 TAG_TYPES = %w(strong div span a ul)

 def self.tag(tag_name, content)
  "<#{tag_name}>#{content}</#{tag_name}>"
 end

 def self.strong(content)
  tag(‘strong’, content)
 end
end

Html.strong(“I’m strong!”)
# <strong>I’m strong!</strong>
class Html
 TAG_TYPES = %w(strong div span a ul)

 class << self
   def tag(tag_name, content)
    "<#{tag_name}>#{content}</
    #{tag_name}>"
   end

  def strong(content)
    tag(‘strong’, content)
  end
 end
end
class Html
 TAG_TYPES = %w(strong div span a ul)

 class << self
   def tag(tag_name, content)
    "<#{tag_name}>#{content}</#{tag_name}>"
   end

  TAG_TYPES.each{|tag_type|
    define_method(tag_type) do |content|
     tag(tag_type, content)
    end
  }
 end
end
Html.strong(‘buffalo’) # <strong>buffalo</strong>

Html.span(‘distances’) # <span>distances</span>

Html.a(‘revelation’) # <a>revelation</a>
class Html
  TAG_TYPES = %w(strong div span a ul)

 class << self
   def tag(tag_name, content)
    "<#{tag_name}>#{content}</#{tag_name}>"
   end

  def method_missing(method, *args)
    if TAG_TYPES.include?(method)
      tag(method, *args)
    else
      super
    end
  end
 end
end
class Html
  class << self
    def tag(tag_name, content)
     "<#{tag_name}>#{content}</#{tag_name}>"
    end

  def method_missing(method, *args)
    tag(method, *args)
  end
 end
end
Html.li(‘list item 1’) # <li>list item 1</li>

Html.think(‘test’) # <think>test</think>

Html.name(‘Steven Soroka’)
# <name>Steven Soroka</name>
Meta Programming in Ruby - Code Camp 2010
Object.methods.size # 75 (or more)
Object.methods.size # 75 (or more)

Object.methods
Object.methods.size # 75 (or more)

Object.methods
# ["inspect", "private_class_method",
"const_missing", ...]
undef_method()

class Html
 class << self
  methods.each{|method|
    undef_method(method)
  }
 end
end
undef_method()



Html.methods # []     ?
undef_method()


NoMethodError: undefined
method `methods' for
#<Class:0x408bc>
XML Builder
xml.instruct!
 xml.html {
   xml.head {
     xml.title("History")
   }
   xml.body {
     xml.h1("Header")
     xml.p("paragraph")
   }
 }
XML Builder
<?xml version="1.0" encoding="UTF-8"?
>
<html>
  <head>
   <title>History</title>
  </head>
  <body>
   <h1>Header</h1>
   <p>paragraph</p>
  </body>
</html>
Singleton Methods


•methods defined on a
 single instance of a class.
•unrelated to class
 singletons
Meta Programming in Ruby - Code Camp 2010
big_button = Button.new
big_button = Button.new
little_button = Button.new
big_button = Button.new
little_button = Button.new

def big_button.click
big_button = Button.new
little_button = Button.new

def big_button.click
  do_big_stuff
big_button = Button.new
little_button = Button.new

def big_button.click
  do_big_stuff
end
big_button = Button.new
little_button = Button.new

def big_button.click
  do_big_stuff
end

def little_button.click
big_button = Button.new
little_button = Button.new

def big_button.click
  do_big_stuff
end

def little_button.click
  act_important
big_button = Button.new
little_button = Button.new

def big_button.click
  do_big_stuff
end

def little_button.click
  act_important
end
Domain-Specific
Language (DSL)
eval


• eval
• class_eval
• instance_eval
• module_eval
module ActiveRecord
 class RecordCannotBeDestroyed < ActiveRecordError
 end

 module Associations
  module ClassMethods
   def refuse_to_destroy!
    module_eval %Q{
      before_destroy do |record|
       raise RecordCannotBeDestroyed, "You cannot destroy
#{record.class.name} records." unless record.new_record?
      end
    }
   end
  end
 end
end
class User < ActiveRecord::Base
  refuse_to_destroy!
end

# @user.destroy now raises an exception
def refuse_to_destroy!
 module_eval %Q{
   before_destroy do |record|
    raise RecordCannotBeDestroyed, "You cannot destroy
#{record.class.name} records." unless record.new_record?
   end
 }
end
car.start
car.reverse
car.wheel.turn
car.gas_pedal.press
car.brake_pedal.press

with car do
 start
 reverse
 wheel.turn
 gas_pedal.press
 brake_pedal.press
end
car.instance_eval {
 start
 reverse
 wheel.turn
 gas_pedal.press
 brake_pedal.press
}
class Object
 def with(obj, &block)
  obj.instance_eval &block
 end
end
with car do
 start
 reverse
 wheel.turn
 gas_pedal.press
 brake_pedal.press
end
Aliasing Methods


• basically copies a method with a new
  name
• alias chaining
• aka: alias method chaining
['apple', 'lobster', 'fish', 'balloons'].include?('fish')
# true

['apple', 'lobster', 'fish', 'balloons'].include?(/(lobster|fish)/)
# false
class Array
 def include_with_regexp?(matcher)
  if matcher.is_a?(Regexp)
    any?{|i| i =~ matcher }
  else
    include_without_regexp?(matcher)
  end
 end

 alias :include_without_regexp? :include?
 alias :include? :include_with_regexp?
end
class Array
 def include_with_regexp?(matcher)
  if matcher.is_a?(Regexp)
    any?{|i| i =~ matcher }
  else
    include_without_regexp?(matcher)
  end
 end

 alias_method_chain :include?, :regexp
end
['apple', 'lobster', 'fish', 'balloons'].include?(
   /(lobster|fish)/)
# true
Operator Overloading
Operator Overloading
class Fixnum
  def +(other)
   self - other
  end
end
Operator Overloading
class Fixnum
  def +(other)
   self - other
  end
end

5 + 3 # => 2
Operator Overloading
Operator Overloading
class Fixnum
  def +(other)
   (self.to_s + other.to_s).to_i
  end
end
Operator Overloading
class Fixnum
  def +(other)
   (self.to_s + other.to_s).to_i
  end
end

5 + 3 # => 53
More Examples


• Object Proxies
• Code that rewrites itself
  • Optimization
  • Caching
Object Proxy
Object Proxy
class SpyProxy
Object Proxy
class SpyProxy
 def initialize(target)
Object Proxy
class SpyProxy
 def initialize(target)
   @target = target
Object Proxy
class SpyProxy
 def initialize(target)
   @target = target
 end
Object Proxy
class SpyProxy
 def initialize(target)
   @target = target
 end

 def method_missing(method, *args)
Object Proxy
class SpyProxy
 def initialize(target)
   @target = target
 end

 def method_missing(method, *args)
  puts “#{method} called with args:
Object Proxy
class SpyProxy
 def initialize(target)
   @target = target
 end

 def method_missing(method, *args)
  puts “#{method} called with args:
   #{args.inspect}”
Object Proxy
class SpyProxy
 def initialize(target)
   @target = target
 end

 def method_missing(method, *args)
  puts “#{method} called with args:
   #{args.inspect}”
  @target.send(method, *args)
Object Proxy
class SpyProxy
 def initialize(target)
   @target = target
 end

 def method_missing(method, *args)
  puts “#{method} called with args:
   #{args.inspect}”
  @target.send(method, *args)
 end
Object Proxy
class SpyProxy
 def initialize(target)
   @target = target
 end

 def method_missing(method, *args)
  puts “#{method} called with args:
    #{args.inspect}”
  @target.send(method, *args)
 end
end
Object Proxy
Object Proxy
paul = Person.new
Object Proxy
paul = Person.new
steve = Person. new
Object Proxy
paul = Person.new
steve = Person. new
bmw = BMW. new
Object Proxy
paul = Person.new
steve = Person. new
bmw = BMW. new

paul.start(bmw) # “clunk clunk”
Object Proxy
paul = Person.new
steve = Person. new
bmw = BMW. new

paul.start(bmw) # “clunk clunk”
steve.start(bmw) # “vroom vroom”
Object Proxy
paul = Person.new
steve = Person. new
bmw = BMW. new

paul.start(bmw) # “clunk clunk”
steve.start(bmw) # “vroom vroom”

spy_bmw = SpyProxy.new(bmw)
Object Proxy
Object Proxy
spy_bmw = SpyProxy.new(bmw)
Object Proxy
spy_bmw = SpyProxy.new(bmw)

steve.start(spy_bmw)
Object Proxy
spy_bmw = SpyProxy.new(bmw)

steve.start(spy_bmw)
# press_clutch called with args: [1.0]
Object Proxy
spy_bmw = SpyProxy.new(bmw)

steve.start(spy_bmw)
# press_clutch called with args: [1.0]
# turn_key called with args: []
Object Proxy
spy_bmw = SpyProxy.new(bmw)

steve.start(spy_bmw)
# press_clutch called with args: [1.0]
# turn_key called with args: []
# “vroom vroom”
Object Proxy
spy_bmw = SpyProxy.new(bmw)

steve.start(spy_bmw)
# press_clutch called with args: [1.0]
# turn_key called with args: []
# “vroom vroom”

paul.start(spy_bmw)
Object Proxy
spy_bmw = SpyProxy.new(bmw)

steve.start(spy_bmw)
# press_clutch called with args: [1.0]
# turn_key called with args: []
# “vroom vroom”

paul.start(spy_bmw)
# turn_key called with args: []
Object Proxy
spy_bmw = SpyProxy.new(bmw)

steve.start(spy_bmw)
# press_clutch called with args: [1.0]
# turn_key called with args: []
# “vroom vroom”

paul.start(spy_bmw)
# turn_key called with args: []
# “clunk clunk”
Self-Optimization
Self-Optimization


def get_random_user_id
Self-Optimization


def get_random_user_id
 user_count = sql("select count(*) from users")
Self-Optimization


def get_random_user_id
 user_count = sql("select count(*) from users")
 sql("select id from users
Self-Optimization


def get_random_user_id
 user_count = sql("select count(*) from users")
 sql("select id from users
   offset #{rand(user_count)} limit 1")
Self-Optimization


def get_random_user_id
 user_count = sql("select count(*) from users")
 sql("select id from users
   offset #{rand(user_count)} limit 1")
end
Self-Optimization
Self-Optimization


def get_random_user_id
 @user_count ||= sql("select count(*) from users")
 sql("select id from users
   offset #{rand(@user_count)} limit 1")
end
Self-Optimization
Self-Optimization

def get_random_user_id
Self-Optimization

def get_random_user_id
 class_eval {
Self-Optimization

def get_random_user_id
 class_eval {
   user_count = sql("select count(*) from users")
Self-Optimization

def get_random_user_id
 class_eval {
   user_count = sql("select count(*) from users")
   define_method(‘get_random_user_id’) do
Self-Optimization

def get_random_user_id
 class_eval {
   user_count = sql("select count(*) from users")
   define_method(‘get_random_user_id’) do
     sql("select id from users
Self-Optimization

def get_random_user_id
 class_eval {
   user_count = sql("select count(*) from users")
   define_method(‘get_random_user_id’) do
     sql("select id from users
       offset #{rand(user_count)} limit 1")
Self-Optimization

def get_random_user_id
 class_eval {
   user_count = sql("select count(*) from users")
   define_method(‘get_random_user_id’) do
     sql("select id from users
       offset #{rand(user_count)} limit 1")
   end
Self-Optimization

def get_random_user_id
 class_eval {
   user_count = sql("select count(*) from users")
   define_method(‘get_random_user_id’) do
     sql("select id from users
       offset #{rand(user_count)} limit 1")
   end
 }
Self-Optimization

def get_random_user_id
 class_eval {
   user_count = sql("select count(*) from users")
   define_method(‘get_random_user_id’) do
     sql("select id from users
       offset #{rand(user_count)} limit 1")
   end
 }
 get_random_user_id
Self-Optimization

def get_random_user_id
 class_eval {
   user_count = sql("select count(*) from users")
   define_method(‘get_random_user_id’) do
     sql("select id from users
       offset #{rand(user_count)} limit 1")
   end
 }
 get_random_user_id
end
Self-Optimization
Self-Optimization


def get_random_user_id
 sql("select id from users
   offset #{rand(1052023)} limit 1")
end
Caching by rewriting
     methods?
Caching by rewriting
       methods?
• You can rewrite a method as a form of
  caching
Caching by rewriting
       methods?
• You can rewrite a method as a form of
  caching

 • Downside is cache invalidation
    becomes messy (doable, think alias)
Caching by rewriting
       methods?
• You can rewrite a method as a form of
  caching

 • Downside is cache invalidation
    becomes messy (doable, think alias)

 • There’s easier ways
Caching by rewriting
       methods?
• You can rewrite a method as a form of
  caching

 • Downside is cache invalidation
    becomes messy (doable, think alias)

 • There’s easier ways
   • @var ||= ...
Caching by rewriting
       methods?
• You can rewrite a method as a form of
  caching

 • Downside is cache invalidation
    becomes messy (doable, think alias)

 • There’s easier ways
   • @var ||= ...
   • memoization (memoize in Rails)
Try Ruby in Your
        Browser
   http://TryRuby.org/


                 Download Ruby
http://www.ruby-lang.org/en/downloads/
http://www.TeachMeToCode.com
Resources


•   http://www.linuxdevcenter.com/pub/a/linux/2001/11/29/ruby.html

•   http://www.ruby-lang.org/en/about

•   http://www.artima.com/intv/closures2.html

•   http://silverlight.net/learn/dynamic-languages/

•   http://blog.headius.com/2008/04/promise-and-peril-for-alternative-ruby.html
Questions?

      @ssoroka - twitter
Merci

    @ssoroka - twitter

More Related Content

What's hot

Ruby and Rails short motivation
Ruby and Rails short motivationRuby and Rails short motivation
Ruby and Rails short motivationjistr
 
Ruby On Rails Overview
Ruby On Rails OverviewRuby On Rails Overview
Ruby On Rails Overviewjonkinney
 
Ruby Programming Language - Introduction
Ruby Programming Language - IntroductionRuby Programming Language - Introduction
Ruby Programming Language - IntroductionKwangshin Oh
 
Griffith uni
Griffith uniGriffith uni
Griffith uninigel99
 
Clojure's take on concurrency
Clojure's take on concurrencyClojure's take on concurrency
Clojure's take on concurrencyyoavrubin
 
Scala for android
Scala for androidScala for android
Scala for androidTack Mobile
 
A Static Type Analyzer of Untyped Ruby Code for Ruby 3
A Static Type Analyzer of Untyped Ruby Code for Ruby 3A Static Type Analyzer of Untyped Ruby Code for Ruby 3
A Static Type Analyzer of Untyped Ruby Code for Ruby 3mametter
 
Frederick web meetup slides
Frederick web meetup slidesFrederick web meetup slides
Frederick web meetup slidesPat Zearfoss
 
Apple Swift API Design Guideline
Apple Swift API Design GuidelineApple Swift API Design Guideline
Apple Swift API Design GuidelineChihyang Li
 
5 stages chain process powerpoint slides.
5 stages chain process powerpoint slides.5 stages chain process powerpoint slides.
5 stages chain process powerpoint slides.SlideTeam.net
 
5 stages chain strategy powerpoint templates.
5 stages chain strategy powerpoint templates.5 stages chain strategy powerpoint templates.
5 stages chain strategy powerpoint templates.SlideTeam.net
 
5 stages chain process powerpoint templates.
5 stages chain process powerpoint templates.5 stages chain process powerpoint templates.
5 stages chain process powerpoint templates.SlideTeam.net
 
5 stages chain strategy powerpoint slides.
5 stages chain strategy powerpoint slides.5 stages chain strategy powerpoint slides.
5 stages chain strategy powerpoint slides.SlideTeam.net
 
A Deep Dive into Javascript
A Deep Dive into JavascriptA Deep Dive into Javascript
A Deep Dive into JavascriptTiang Cheng
 
Beginning Java for .NET developers
Beginning Java for .NET developersBeginning Java for .NET developers
Beginning Java for .NET developersAndrei Rinea
 

What's hot (20)

OOP in JS
OOP in JSOOP in JS
OOP in JS
 
Ruby and Rails short motivation
Ruby and Rails short motivationRuby and Rails short motivation
Ruby and Rails short motivation
 
Ruby On Rails Overview
Ruby On Rails OverviewRuby On Rails Overview
Ruby On Rails Overview
 
PHP Classroom Training
PHP Classroom TrainingPHP Classroom Training
PHP Classroom Training
 
Rails traps
Rails trapsRails traps
Rails traps
 
Ruby Programming Language - Introduction
Ruby Programming Language - IntroductionRuby Programming Language - Introduction
Ruby Programming Language - Introduction
 
Haskell Tour (Part 1)
Haskell Tour (Part 1)Haskell Tour (Part 1)
Haskell Tour (Part 1)
 
Griffith uni
Griffith uniGriffith uni
Griffith uni
 
Clojure's take on concurrency
Clojure's take on concurrencyClojure's take on concurrency
Clojure's take on concurrency
 
Scala for android
Scala for androidScala for android
Scala for android
 
A Static Type Analyzer of Untyped Ruby Code for Ruby 3
A Static Type Analyzer of Untyped Ruby Code for Ruby 3A Static Type Analyzer of Untyped Ruby Code for Ruby 3
A Static Type Analyzer of Untyped Ruby Code for Ruby 3
 
Frederick web meetup slides
Frederick web meetup slidesFrederick web meetup slides
Frederick web meetup slides
 
Apple Swift API Design Guideline
Apple Swift API Design GuidelineApple Swift API Design Guideline
Apple Swift API Design Guideline
 
A Tale of Two Rubies
A Tale of Two RubiesA Tale of Two Rubies
A Tale of Two Rubies
 
5 stages chain process powerpoint slides.
5 stages chain process powerpoint slides.5 stages chain process powerpoint slides.
5 stages chain process powerpoint slides.
 
5 stages chain strategy powerpoint templates.
5 stages chain strategy powerpoint templates.5 stages chain strategy powerpoint templates.
5 stages chain strategy powerpoint templates.
 
5 stages chain process powerpoint templates.
5 stages chain process powerpoint templates.5 stages chain process powerpoint templates.
5 stages chain process powerpoint templates.
 
5 stages chain strategy powerpoint slides.
5 stages chain strategy powerpoint slides.5 stages chain strategy powerpoint slides.
5 stages chain strategy powerpoint slides.
 
A Deep Dive into Javascript
A Deep Dive into JavascriptA Deep Dive into Javascript
A Deep Dive into Javascript
 
Beginning Java for .NET developers
Beginning Java for .NET developersBeginning Java for .NET developers
Beginning Java for .NET developers
 

Viewers also liked

KoprowskiT_SQLAzureLandingInBelfast
KoprowskiT_SQLAzureLandingInBelfastKoprowskiT_SQLAzureLandingInBelfast
KoprowskiT_SQLAzureLandingInBelfastTobias Koprowski
 
Wysoka Dostępność SQL Server 2008 w kontekscie umów SLA
Wysoka Dostępność SQL Server 2008 w kontekscie umów SLAWysoka Dostępność SQL Server 2008 w kontekscie umów SLA
Wysoka Dostępność SQL Server 2008 w kontekscie umów SLATobias Koprowski
 
KoprowskiT_SQLSatMoscow_WASDforBeginners
KoprowskiT_SQLSatMoscow_WASDforBeginnersKoprowskiT_SQLSatMoscow_WASDforBeginners
KoprowskiT_SQLSatMoscow_WASDforBeginnersTobias Koprowski
 
Tomasz Kopacz MTS 2012 Azure - Co i kiedy użyć (IaaS vs paas vshybrid cloud v...
Tomasz Kopacz MTS 2012 Azure - Co i kiedy użyć (IaaS vs paas vshybrid cloud v...Tomasz Kopacz MTS 2012 Azure - Co i kiedy użyć (IaaS vs paas vshybrid cloud v...
Tomasz Kopacz MTS 2012 Azure - Co i kiedy użyć (IaaS vs paas vshybrid cloud v...Tomasz Kopacz
 
Scott Bennett - Shell Game - Whistleblowing Report
Scott Bennett - Shell Game - Whistleblowing ReportScott Bennett - Shell Game - Whistleblowing Report
Scott Bennett - Shell Game - Whistleblowing ReportExopolitics Hungary
 
PLSSUG Meeting - Wysoka dostepność SQL Server 2008 w kontekscie umów SLA
PLSSUG Meeting - Wysoka dostepność SQL Server 2008 w kontekscie umów SLAPLSSUG Meeting - Wysoka dostepność SQL Server 2008 w kontekscie umów SLA
PLSSUG Meeting - Wysoka dostepność SQL Server 2008 w kontekscie umów SLATobias Koprowski
 
Beginning to Spatial Data in SQL Server 2008
Beginning to Spatial Data in SQL Server 2008Beginning to Spatial Data in SQL Server 2008
Beginning to Spatial Data in SQL Server 2008Tobias Koprowski
 
KoprowskiT_SQLSatMoscow_2AMaDisaterJustBegan
KoprowskiT_SQLSatMoscow_2AMaDisaterJustBeganKoprowskiT_SQLSatMoscow_2AMaDisaterJustBegan
KoprowskiT_SQLSatMoscow_2AMaDisaterJustBeganTobias Koprowski
 
KoprowskiT_SQLRelayBirmingham_SQLSecurityInTheClouds
KoprowskiT_SQLRelayBirmingham_SQLSecurityInTheCloudsKoprowskiT_SQLRelayBirmingham_SQLSecurityInTheClouds
KoprowskiT_SQLRelayBirmingham_SQLSecurityInTheCloudsTobias Koprowski
 
KoprowskiT_PASSEastMidsFEB16_2AMaDisasterJustBegan
KoprowskiT_PASSEastMidsFEB16_2AMaDisasterJustBeganKoprowskiT_PASSEastMidsFEB16_2AMaDisasterJustBegan
KoprowskiT_PASSEastMidsFEB16_2AMaDisasterJustBeganTobias Koprowski
 
Introduction to SQL Server Analysis services 2008
Introduction to SQL Server Analysis services 2008Introduction to SQL Server Analysis services 2008
Introduction to SQL Server Analysis services 2008Tobias Koprowski
 
Eventuosity For Event Producers and Service Providers
Eventuosity For Event Producers and Service ProvidersEventuosity For Event Producers and Service Providers
Eventuosity For Event Producers and Service ProvidersJustin Panzer
 
Презентация стратегической игры MatriX Urban
Презентация стратегической игры MatriX UrbanПрезентация стратегической игры MatriX Urban
Презентация стратегической игры MatriX UrbanАндрей Донских
 
Virtual Study Beta Exam 71-663 Exchange 2010 Designing And Deploying Messagin...
Virtual Study Beta Exam 71-663 Exchange 2010 Designing And Deploying Messagin...Virtual Study Beta Exam 71-663 Exchange 2010 Designing And Deploying Messagin...
Virtual Study Beta Exam 71-663 Exchange 2010 Designing And Deploying Messagin...Tobias Koprowski
 
Can We Automate Predictive Analytics
Can We Automate Predictive AnalyticsCan We Automate Predictive Analytics
Can We Automate Predictive Analyticsodsc
 
Cabs, Cassandra, and Hailo
Cabs, Cassandra, and HailoCabs, Cassandra, and Hailo
Cabs, Cassandra, and HailoDave Gardner
 
Slideburst #7 - Next Best Action in All Digital Channels
Slideburst #7 - Next Best Action in All Digital ChannelsSlideburst #7 - Next Best Action in All Digital Channels
Slideburst #7 - Next Best Action in All Digital ChannelsPatrik Svensson
 
ERISA Expert Advocates for 401(k) Loan Default Protection
ERISA Expert Advocates for 401(k) Loan Default ProtectionERISA Expert Advocates for 401(k) Loan Default Protection
ERISA Expert Advocates for 401(k) Loan Default ProtectionRetirement Loan Eraser
 

Viewers also liked (20)

KoprowskiT_SQLAzureLandingInBelfast
KoprowskiT_SQLAzureLandingInBelfastKoprowskiT_SQLAzureLandingInBelfast
KoprowskiT_SQLAzureLandingInBelfast
 
Wysoka Dostępność SQL Server 2008 w kontekscie umów SLA
Wysoka Dostępność SQL Server 2008 w kontekscie umów SLAWysoka Dostępność SQL Server 2008 w kontekscie umów SLA
Wysoka Dostępność SQL Server 2008 w kontekscie umów SLA
 
KoprowskiT_SQLSatMoscow_WASDforBeginners
KoprowskiT_SQLSatMoscow_WASDforBeginnersKoprowskiT_SQLSatMoscow_WASDforBeginners
KoprowskiT_SQLSatMoscow_WASDforBeginners
 
Tomasz Kopacz MTS 2012 Azure - Co i kiedy użyć (IaaS vs paas vshybrid cloud v...
Tomasz Kopacz MTS 2012 Azure - Co i kiedy użyć (IaaS vs paas vshybrid cloud v...Tomasz Kopacz MTS 2012 Azure - Co i kiedy użyć (IaaS vs paas vshybrid cloud v...
Tomasz Kopacz MTS 2012 Azure - Co i kiedy użyć (IaaS vs paas vshybrid cloud v...
 
Scott Bennett - Shell Game - Whistleblowing Report
Scott Bennett - Shell Game - Whistleblowing ReportScott Bennett - Shell Game - Whistleblowing Report
Scott Bennett - Shell Game - Whistleblowing Report
 
PLSSUG Meeting - Wysoka dostepność SQL Server 2008 w kontekscie umów SLA
PLSSUG Meeting - Wysoka dostepność SQL Server 2008 w kontekscie umów SLAPLSSUG Meeting - Wysoka dostepność SQL Server 2008 w kontekscie umów SLA
PLSSUG Meeting - Wysoka dostepność SQL Server 2008 w kontekscie umów SLA
 
State of Nation - Feb 2017
State of Nation - Feb 2017State of Nation - Feb 2017
State of Nation - Feb 2017
 
Beginning to Spatial Data in SQL Server 2008
Beginning to Spatial Data in SQL Server 2008Beginning to Spatial Data in SQL Server 2008
Beginning to Spatial Data in SQL Server 2008
 
KoprowskiT_SQLSatMoscow_2AMaDisaterJustBegan
KoprowskiT_SQLSatMoscow_2AMaDisaterJustBeganKoprowskiT_SQLSatMoscow_2AMaDisaterJustBegan
KoprowskiT_SQLSatMoscow_2AMaDisaterJustBegan
 
KoprowskiT_SQLRelayBirmingham_SQLSecurityInTheClouds
KoprowskiT_SQLRelayBirmingham_SQLSecurityInTheCloudsKoprowskiT_SQLRelayBirmingham_SQLSecurityInTheClouds
KoprowskiT_SQLRelayBirmingham_SQLSecurityInTheClouds
 
KoprowskiT_PASSEastMidsFEB16_2AMaDisasterJustBegan
KoprowskiT_PASSEastMidsFEB16_2AMaDisasterJustBeganKoprowskiT_PASSEastMidsFEB16_2AMaDisasterJustBegan
KoprowskiT_PASSEastMidsFEB16_2AMaDisasterJustBegan
 
Introduction to SQL Server Analysis services 2008
Introduction to SQL Server Analysis services 2008Introduction to SQL Server Analysis services 2008
Introduction to SQL Server Analysis services 2008
 
Eventuosity For Event Producers and Service Providers
Eventuosity For Event Producers and Service ProvidersEventuosity For Event Producers and Service Providers
Eventuosity For Event Producers and Service Providers
 
Презентация стратегической игры MatriX Urban
Презентация стратегической игры MatriX UrbanПрезентация стратегической игры MatriX Urban
Презентация стратегической игры MatriX Urban
 
Virtual Study Beta Exam 71-663 Exchange 2010 Designing And Deploying Messagin...
Virtual Study Beta Exam 71-663 Exchange 2010 Designing And Deploying Messagin...Virtual Study Beta Exam 71-663 Exchange 2010 Designing And Deploying Messagin...
Virtual Study Beta Exam 71-663 Exchange 2010 Designing And Deploying Messagin...
 
Can We Automate Predictive Analytics
Can We Automate Predictive AnalyticsCan We Automate Predictive Analytics
Can We Automate Predictive Analytics
 
Das Next Best Offer-Konzept
Das Next Best Offer-KonzeptDas Next Best Offer-Konzept
Das Next Best Offer-Konzept
 
Cabs, Cassandra, and Hailo
Cabs, Cassandra, and HailoCabs, Cassandra, and Hailo
Cabs, Cassandra, and Hailo
 
Slideburst #7 - Next Best Action in All Digital Channels
Slideburst #7 - Next Best Action in All Digital ChannelsSlideburst #7 - Next Best Action in All Digital Channels
Slideburst #7 - Next Best Action in All Digital Channels
 
ERISA Expert Advocates for 401(k) Loan Default Protection
ERISA Expert Advocates for 401(k) Loan Default ProtectionERISA Expert Advocates for 401(k) Loan Default Protection
ERISA Expert Advocates for 401(k) Loan Default Protection
 

Similar to Meta Programming in Ruby - Code Camp 2010

Learn Ruby 2011 - Session 2
Learn Ruby 2011 - Session 2Learn Ruby 2011 - Session 2
Learn Ruby 2011 - Session 2James Thompson
 
Day 1 - Intro to Ruby
Day 1 - Intro to RubyDay 1 - Intro to Ruby
Day 1 - Intro to RubyBarry Jones
 
Ruby an overall approach
Ruby an overall approachRuby an overall approach
Ruby an overall approachFelipe Schmitt
 
Ruby :: Training 1
Ruby :: Training 1Ruby :: Training 1
Ruby :: Training 1Pavel Tyk
 
Funtional Ruby - Mikhail Bortnyk
Funtional Ruby - Mikhail BortnykFuntional Ruby - Mikhail Bortnyk
Funtional Ruby - Mikhail BortnykRuby Meditation
 
What can Ruby learn from Python (and vice versa)?
What can Ruby learn from Python (and vice versa)?What can Ruby learn from Python (and vice versa)?
What can Ruby learn from Python (and vice versa)?Reuven Lerner
 
Code for Startup MVP (Ruby on Rails) Session 2
Code for Startup MVP (Ruby on Rails) Session 2Code for Startup MVP (Ruby on Rails) Session 2
Code for Startup MVP (Ruby on Rails) Session 2Henry S
 
Not Everything is an Object - Rocksolid Tour 2013
Not Everything is an Object  - Rocksolid Tour 2013Not Everything is an Object  - Rocksolid Tour 2013
Not Everything is an Object - Rocksolid Tour 2013Gary Short
 
Rapid Application Development using Ruby on Rails
Rapid Application Development using Ruby on RailsRapid Application Development using Ruby on Rails
Rapid Application Development using Ruby on RailsSimobo
 
Charles nutter star techconf 2011 - jvm languages
Charles nutter   star techconf 2011 - jvm languagesCharles nutter   star techconf 2011 - jvm languages
Charles nutter star techconf 2011 - jvm languagesStarTech Conference
 
Rails development environment talk
Rails development environment talkRails development environment talk
Rails development environment talkReuven Lerner
 

Similar to Meta Programming in Ruby - Code Camp 2010 (20)

Learn Ruby 2011 - Session 2
Learn Ruby 2011 - Session 2Learn Ruby 2011 - Session 2
Learn Ruby 2011 - Session 2
 
Ruby basics
Ruby basicsRuby basics
Ruby basics
 
Day 1 - Intro to Ruby
Day 1 - Intro to RubyDay 1 - Intro to Ruby
Day 1 - Intro to Ruby
 
Ruby an overall approach
Ruby an overall approachRuby an overall approach
Ruby an overall approach
 
Ruby :: Training 1
Ruby :: Training 1Ruby :: Training 1
Ruby :: Training 1
 
Testing gone-right
Testing gone-rightTesting gone-right
Testing gone-right
 
Functional Ruby
Functional RubyFunctional Ruby
Functional Ruby
 
Funtional Ruby - Mikhail Bortnyk
Funtional Ruby - Mikhail BortnykFuntional Ruby - Mikhail Bortnyk
Funtional Ruby - Mikhail Bortnyk
 
RoR_2_Ruby
RoR_2_RubyRoR_2_Ruby
RoR_2_Ruby
 
Javascript
JavascriptJavascript
Javascript
 
JRuby: The Hard Parts
JRuby: The Hard PartsJRuby: The Hard Parts
JRuby: The Hard Parts
 
What can Ruby learn from Python (and vice versa)?
What can Ruby learn from Python (and vice versa)?What can Ruby learn from Python (and vice versa)?
What can Ruby learn from Python (and vice versa)?
 
Code for Startup MVP (Ruby on Rails) Session 2
Code for Startup MVP (Ruby on Rails) Session 2Code for Startup MVP (Ruby on Rails) Session 2
Code for Startup MVP (Ruby on Rails) Session 2
 
Not Everything is an Object - Rocksolid Tour 2013
Not Everything is an Object  - Rocksolid Tour 2013Not Everything is an Object  - Rocksolid Tour 2013
Not Everything is an Object - Rocksolid Tour 2013
 
Rapid Application Development using Ruby on Rails
Rapid Application Development using Ruby on RailsRapid Application Development using Ruby on Rails
Rapid Application Development using Ruby on Rails
 
Week2
Week2Week2
Week2
 
Polyglot Grails
Polyglot GrailsPolyglot Grails
Polyglot Grails
 
Ruby
RubyRuby
Ruby
 
Charles nutter star techconf 2011 - jvm languages
Charles nutter   star techconf 2011 - jvm languagesCharles nutter   star techconf 2011 - jvm languages
Charles nutter star techconf 2011 - jvm languages
 
Rails development environment talk
Rails development environment talkRails development environment talk
Rails development environment talk
 

Recently uploaded

Do we need a new standard for visualizing the invisible?
Do we need a new standard for visualizing the invisible?Do we need a new standard for visualizing the invisible?
Do we need a new standard for visualizing the invisible?SANGHEE SHIN
 
Basic Building Blocks of Internet of Things.
Basic Building Blocks of Internet of Things.Basic Building Blocks of Internet of Things.
Basic Building Blocks of Internet of Things.YounusS2
 
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019IES VE
 
Meet the new FSP 3000 M-Flex800™
Meet the new FSP 3000 M-Flex800™Meet the new FSP 3000 M-Flex800™
Meet the new FSP 3000 M-Flex800™Adtran
 
Bird eye's view on Camunda open source ecosystem
Bird eye's view on Camunda open source ecosystemBird eye's view on Camunda open source ecosystem
Bird eye's view on Camunda open source ecosystemAsko Soukka
 
Cloud Revolution: Exploring the New Wave of Serverless Spatial Data
Cloud Revolution: Exploring the New Wave of Serverless Spatial DataCloud Revolution: Exploring the New Wave of Serverless Spatial Data
Cloud Revolution: Exploring the New Wave of Serverless Spatial DataSafe Software
 
Salesforce Miami User Group Event - 1st Quarter 2024
Salesforce Miami User Group Event - 1st Quarter 2024Salesforce Miami User Group Event - 1st Quarter 2024
Salesforce Miami User Group Event - 1st Quarter 2024SkyPlanner
 
IaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdf
IaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdfIaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdf
IaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdfDaniel Santiago Silva Capera
 
UiPath Studio Web workshop series - Day 6
UiPath Studio Web workshop series - Day 6UiPath Studio Web workshop series - Day 6
UiPath Studio Web workshop series - Day 6DianaGray10
 
UiPath Studio Web workshop series - Day 8
UiPath Studio Web workshop series - Day 8UiPath Studio Web workshop series - Day 8
UiPath Studio Web workshop series - Day 8DianaGray10
 
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...DianaGray10
 
Empowering Africa's Next Generation: The AI Leadership Blueprint
Empowering Africa's Next Generation: The AI Leadership BlueprintEmpowering Africa's Next Generation: The AI Leadership Blueprint
Empowering Africa's Next Generation: The AI Leadership BlueprintMahmoud Rabie
 
9 Steps For Building Winning Founding Team
9 Steps For Building Winning Founding Team9 Steps For Building Winning Founding Team
9 Steps For Building Winning Founding TeamAdam Moalla
 
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...Will Schroeder
 
UiPath Solutions Management Preview - Northern CA Chapter - March 22.pdf
UiPath Solutions Management Preview - Northern CA Chapter - March 22.pdfUiPath Solutions Management Preview - Northern CA Chapter - March 22.pdf
UiPath Solutions Management Preview - Northern CA Chapter - March 22.pdfDianaGray10
 
Babel Compiler - Transforming JavaScript for All Browsers.pptx
Babel Compiler - Transforming JavaScript for All Browsers.pptxBabel Compiler - Transforming JavaScript for All Browsers.pptx
Babel Compiler - Transforming JavaScript for All Browsers.pptxYounusS2
 
UiPath Community: AI for UiPath Automation Developers
UiPath Community: AI for UiPath Automation DevelopersUiPath Community: AI for UiPath Automation Developers
UiPath Community: AI for UiPath Automation DevelopersUiPathCommunity
 
Introduction to Quantum Computing
Introduction to Quantum ComputingIntroduction to Quantum Computing
Introduction to Quantum ComputingGDSC PJATK
 
Computer 10: Lesson 10 - Online Crimes and Hazards
Computer 10: Lesson 10 - Online Crimes and HazardsComputer 10: Lesson 10 - Online Crimes and Hazards
Computer 10: Lesson 10 - Online Crimes and HazardsSeth Reyes
 
NIST Cybersecurity Framework (CSF) 2.0 Workshop
NIST Cybersecurity Framework (CSF) 2.0 WorkshopNIST Cybersecurity Framework (CSF) 2.0 Workshop
NIST Cybersecurity Framework (CSF) 2.0 WorkshopBachir Benyammi
 

Recently uploaded (20)

Do we need a new standard for visualizing the invisible?
Do we need a new standard for visualizing the invisible?Do we need a new standard for visualizing the invisible?
Do we need a new standard for visualizing the invisible?
 
Basic Building Blocks of Internet of Things.
Basic Building Blocks of Internet of Things.Basic Building Blocks of Internet of Things.
Basic Building Blocks of Internet of Things.
 
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019
 
Meet the new FSP 3000 M-Flex800™
Meet the new FSP 3000 M-Flex800™Meet the new FSP 3000 M-Flex800™
Meet the new FSP 3000 M-Flex800™
 
Bird eye's view on Camunda open source ecosystem
Bird eye's view on Camunda open source ecosystemBird eye's view on Camunda open source ecosystem
Bird eye's view on Camunda open source ecosystem
 
Cloud Revolution: Exploring the New Wave of Serverless Spatial Data
Cloud Revolution: Exploring the New Wave of Serverless Spatial DataCloud Revolution: Exploring the New Wave of Serverless Spatial Data
Cloud Revolution: Exploring the New Wave of Serverless Spatial Data
 
Salesforce Miami User Group Event - 1st Quarter 2024
Salesforce Miami User Group Event - 1st Quarter 2024Salesforce Miami User Group Event - 1st Quarter 2024
Salesforce Miami User Group Event - 1st Quarter 2024
 
IaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdf
IaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdfIaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdf
IaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdf
 
UiPath Studio Web workshop series - Day 6
UiPath Studio Web workshop series - Day 6UiPath Studio Web workshop series - Day 6
UiPath Studio Web workshop series - Day 6
 
UiPath Studio Web workshop series - Day 8
UiPath Studio Web workshop series - Day 8UiPath Studio Web workshop series - Day 8
UiPath Studio Web workshop series - Day 8
 
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
 
Empowering Africa's Next Generation: The AI Leadership Blueprint
Empowering Africa's Next Generation: The AI Leadership BlueprintEmpowering Africa's Next Generation: The AI Leadership Blueprint
Empowering Africa's Next Generation: The AI Leadership Blueprint
 
9 Steps For Building Winning Founding Team
9 Steps For Building Winning Founding Team9 Steps For Building Winning Founding Team
9 Steps For Building Winning Founding Team
 
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...
 
UiPath Solutions Management Preview - Northern CA Chapter - March 22.pdf
UiPath Solutions Management Preview - Northern CA Chapter - March 22.pdfUiPath Solutions Management Preview - Northern CA Chapter - March 22.pdf
UiPath Solutions Management Preview - Northern CA Chapter - March 22.pdf
 
Babel Compiler - Transforming JavaScript for All Browsers.pptx
Babel Compiler - Transforming JavaScript for All Browsers.pptxBabel Compiler - Transforming JavaScript for All Browsers.pptx
Babel Compiler - Transforming JavaScript for All Browsers.pptx
 
UiPath Community: AI for UiPath Automation Developers
UiPath Community: AI for UiPath Automation DevelopersUiPath Community: AI for UiPath Automation Developers
UiPath Community: AI for UiPath Automation Developers
 
Introduction to Quantum Computing
Introduction to Quantum ComputingIntroduction to Quantum Computing
Introduction to Quantum Computing
 
Computer 10: Lesson 10 - Online Crimes and Hazards
Computer 10: Lesson 10 - Online Crimes and HazardsComputer 10: Lesson 10 - Online Crimes and Hazards
Computer 10: Lesson 10 - Online Crimes and Hazards
 
NIST Cybersecurity Framework (CSF) 2.0 Workshop
NIST Cybersecurity Framework (CSF) 2.0 WorkshopNIST Cybersecurity Framework (CSF) 2.0 Workshop
NIST Cybersecurity Framework (CSF) 2.0 Workshop
 

Meta Programming in Ruby - Code Camp 2010

Editor's Notes

  1. And yes, the site is in Ruby on Rails.
  2. ruby-lang dot org describes it as....
  3. what does author say?
  4. what does author say?
  5. 2. Scripting language, but don&amp;#x2019;t call it php.4. smoothly elegant6. Ruby is also totally free. Not only free of charge, but also free to use, copy, modify, and distribute.
  6. 2. Scripting language, but don&amp;#x2019;t call it php.4. smoothly elegant6. Ruby is also totally free. Not only free of charge, but also free to use, copy, modify, and distribute.
  7. 2. Scripting language, but don&amp;#x2019;t call it php.4. smoothly elegant6. Ruby is also totally free. Not only free of charge, but also free to use, copy, modify, and distribute.
  8. 2. Scripting language, but don&amp;#x2019;t call it php.4. smoothly elegant6. Ruby is also totally free. Not only free of charge, but also free to use, copy, modify, and distribute.
  9. 2. Scripting language, but don&amp;#x2019;t call it php.4. smoothly elegant6. Ruby is also totally free. Not only free of charge, but also free to use, copy, modify, and distribute.
  10. 2. Scripting language, but don&amp;#x2019;t call it php.4. smoothly elegant6. Ruby is also totally free. Not only free of charge, but also free to use, copy, modify, and distribute.
  11. simplest thing that could possibly work No libraries to import, no main declaration, no instantiation of string classes This, is a thing of beauty.
  12. Lets just get an idea of the syntax. Notice I don&amp;#x2019;t have to declare the type of the car variable, it&amp;#x2019;s automatically assigned at runtime.
  13. Lets just get an idea of the syntax. Notice I don&amp;#x2019;t have to declare the type of the car variable, it&amp;#x2019;s automatically assigned at runtime.
  14. Lets just get an idea of the syntax. Notice I don&amp;#x2019;t have to declare the type of the car variable, it&amp;#x2019;s automatically assigned at runtime.
  15. Lets just get an idea of the syntax. Notice I don&amp;#x2019;t have to declare the type of the car variable, it&amp;#x2019;s automatically assigned at runtime.
  16. Lets just get an idea of the syntax. Notice I don&amp;#x2019;t have to declare the type of the car variable, it&amp;#x2019;s automatically assigned at runtime.
  17. Lets just get an idea of the syntax. Notice I don&amp;#x2019;t have to declare the type of the car variable, it&amp;#x2019;s automatically assigned at runtime.
  18. Lets just get an idea of the syntax. Notice I don&amp;#x2019;t have to declare the type of the car variable, it&amp;#x2019;s automatically assigned at runtime.
  19. This is all fine and dandy, but does Ruby matter? I&amp;#x2019;d argue that it&amp;#x2019;s important. If you can judge that by the number of Ruby implementations, then I&amp;#x2019;d say so. IronMonkey is Adobe VM HotRuby is Ruby interpreter implemented in JS IronRuby is Microsoft&amp;#x2019;s work towards Ruby.NET
  20. This is all fine and dandy, but does Ruby matter? I&amp;#x2019;d argue that it&amp;#x2019;s important. If you can judge that by the number of Ruby implementations, then I&amp;#x2019;d say so. IronMonkey is Adobe VM HotRuby is Ruby interpreter implemented in JS IronRuby is Microsoft&amp;#x2019;s work towards Ruby.NET
  21. This is all fine and dandy, but does Ruby matter? I&amp;#x2019;d argue that it&amp;#x2019;s important. If you can judge that by the number of Ruby implementations, then I&amp;#x2019;d say so. IronMonkey is Adobe VM HotRuby is Ruby interpreter implemented in JS IronRuby is Microsoft&amp;#x2019;s work towards Ruby.NET
  22. This is all fine and dandy, but does Ruby matter? I&amp;#x2019;d argue that it&amp;#x2019;s important. If you can judge that by the number of Ruby implementations, then I&amp;#x2019;d say so. IronMonkey is Adobe VM HotRuby is Ruby interpreter implemented in JS IronRuby is Microsoft&amp;#x2019;s work towards Ruby.NET
  23. This is all fine and dandy, but does Ruby matter? I&amp;#x2019;d argue that it&amp;#x2019;s important. If you can judge that by the number of Ruby implementations, then I&amp;#x2019;d say so. IronMonkey is Adobe VM HotRuby is Ruby interpreter implemented in JS IronRuby is Microsoft&amp;#x2019;s work towards Ruby.NET
  24. This is all fine and dandy, but does Ruby matter? I&amp;#x2019;d argue that it&amp;#x2019;s important. If you can judge that by the number of Ruby implementations, then I&amp;#x2019;d say so. IronMonkey is Adobe VM HotRuby is Ruby interpreter implemented in JS IronRuby is Microsoft&amp;#x2019;s work towards Ruby.NET
  25. This is all fine and dandy, but does Ruby matter? I&amp;#x2019;d argue that it&amp;#x2019;s important. If you can judge that by the number of Ruby implementations, then I&amp;#x2019;d say so. IronMonkey is Adobe VM HotRuby is Ruby interpreter implemented in JS IronRuby is Microsoft&amp;#x2019;s work towards Ruby.NET
  26. This is all fine and dandy, but does Ruby matter? I&amp;#x2019;d argue that it&amp;#x2019;s important. If you can judge that by the number of Ruby implementations, then I&amp;#x2019;d say so. IronMonkey is Adobe VM HotRuby is Ruby interpreter implemented in JS IronRuby is Microsoft&amp;#x2019;s work towards Ruby.NET
  27. This is all fine and dandy, but does Ruby matter? I&amp;#x2019;d argue that it&amp;#x2019;s important. If you can judge that by the number of Ruby implementations, then I&amp;#x2019;d say so. IronMonkey is Adobe VM HotRuby is Ruby interpreter implemented in JS IronRuby is Microsoft&amp;#x2019;s work towards Ruby.NET
  28. This is all fine and dandy, but does Ruby matter? I&amp;#x2019;d argue that it&amp;#x2019;s important. If you can judge that by the number of Ruby implementations, then I&amp;#x2019;d say so. IronMonkey is Adobe VM HotRuby is Ruby interpreter implemented in JS IronRuby is Microsoft&amp;#x2019;s work towards Ruby.NET
  29. The Silverlight Dynamic Languages SDK includes IronRuby, which allows you to write Ruby that runs in the browser
  30. The Silverlight Dynamic Languages SDK includes IronRuby, which allows you to write Ruby that runs in the browser
  31. The Silverlight Dynamic Languages SDK includes IronRuby, which allows you to write Ruby that runs in the browser
  32. The Silverlight Dynamic Languages SDK includes IronRuby, which allows you to write Ruby that runs in the browser
  33. The Silverlight Dynamic Languages SDK includes IronRuby, which allows you to write Ruby that runs in the browser
  34. Here&amp;#x2019;s an example of the GUI you can make with the WxRuby toolkit from Ruby
  35. Here&amp;#x2019;s the exact same library and code run on a Mac. Notice both are native to their own OS.
  36. Let&amp;#x2019;s get familiar with Ruby. We&amp;#x2019;re going to cover a lot of topics really quickly, so keep up. :)
  37. important @ less important @@ global $, if you litter your code with these; your peers will surprise you at how creative they can be when it comes to hiding your lifeless body.
  38. important @ less important @@ global $, if you litter your code with these; your peers will surprise you at how creative they can be when it comes to hiding your lifeless body.
  39. important @ less important @@ global $, if you litter your code with these; your peers will surprise you at how creative they can be when it comes to hiding your lifeless body.
  40. important @ less important @@ global $, if you litter your code with these; your peers will surprise you at how creative they can be when it comes to hiding your lifeless body.
  41. local variables
  42. This is what a symbol looks like. you can think of it as a string, and it is similar, but it&amp;#x2019;s got a key difference which I&amp;#x2019;ll get in to. In Ruby, symbols are mostly used as hash keys, column names, for referencing data types, or used as contant values, but they are not just cheap strings.
  43. This is what a symbol looks like. you can think of it as a string, and it is similar, but it&amp;#x2019;s got a key difference which I&amp;#x2019;ll get in to. In Ruby, symbols are mostly used as hash keys, column names, for referencing data types, or used as contant values, but they are not just cheap strings.
  44. This is what a symbol looks like. you can think of it as a string, and it is similar, but it&amp;#x2019;s got a key difference which I&amp;#x2019;ll get in to. In Ruby, symbols are mostly used as hash keys, column names, for referencing data types, or used as contant values, but they are not just cheap strings.
  45. This is what a symbol looks like. you can think of it as a string, and it is similar, but it&amp;#x2019;s got a key difference which I&amp;#x2019;ll get in to. In Ruby, symbols are mostly used as hash keys, column names, for referencing data types, or used as contant values, but they are not just cheap strings.
  46. The two name symbols here are literally the exact same object, where as the two name strings below are two separate objects that happen to have the same value.
  47. The two name symbols here are literally the exact same object, where as the two name strings below are two separate objects that happen to have the same value.
  48. The two name symbols here are literally the exact same object, where as the two name strings below are two separate objects that happen to have the same value.
  49. The two name symbols here are literally the exact same object, where as the two name strings below are two separate objects that happen to have the same value.
  50. curly braces represent a key-value hash, not a block of code ; the hash has keys and values ;; you can fetch the value for the keys
  51. curly braces represent a key-value hash, not a block of code ; the hash has keys and values ;; you can fetch the value for the keys
  52. curly braces represent a key-value hash, not a block of code ; the hash has keys and values ;; you can fetch the value for the keys
  53. curly braces represent a key-value hash, not a block of code ; the hash has keys and values ;; you can fetch the value for the keys
  54. curly braces represent a key-value hash, not a block of code ; the hash has keys and values ;; you can fetch the value for the keys
  55. curly braces represent a key-value hash, not a block of code ; the hash has keys and values ;; you can fetch the value for the keys
  56. {1}{2}, for example...
  57. {1}{2}, for example...
  58. means: you can change or extend any class. Good practices are up to you OCP is ..
  59. means: you can change or extend any class. Good practices are up to you OCP is ..
  60. means: you can change or extend any class. Good practices are up to you OCP is ..
  61. means: you can change or extend any class. Good practices are up to you OCP is ..
  62. lets reopen the Float class, and maybe our app doesn&amp;#x2019;t want to round up ever. Our new CEO says rounding up is bad for business and we want to redefine round to call floor. Now 5.7.round always returns 5. This is clearly a double-edged sword. You want to open classes for extension, not for modification as we&amp;#x2019;ve done here. This violates the OCP
  63. lets reopen the Float class, and maybe our app doesn&amp;#x2019;t want to round up ever. Our new CEO says rounding up is bad for business and we want to redefine round to call floor. Now 5.7.round always returns 5. This is clearly a double-edged sword. You want to open classes for extension, not for modification as we&amp;#x2019;ve done here. This violates the OCP
  64. lets reopen the Float class, and maybe our app doesn&amp;#x2019;t want to round up ever. Our new CEO says rounding up is bad for business and we want to redefine round to call floor. Now 5.7.round always returns 5. This is clearly a double-edged sword. You want to open classes for extension, not for modification as we&amp;#x2019;ve done here. This violates the OCP
  65. lets reopen the Float class, and maybe our app doesn&amp;#x2019;t want to round up ever. Our new CEO says rounding up is bad for business and we want to redefine round to call floor. Now 5.7.round always returns 5. This is clearly a double-edged sword. You want to open classes for extension, not for modification as we&amp;#x2019;ve done here. This violates the OCP
  66. lets reopen the Float class, and maybe our app doesn&amp;#x2019;t want to round up ever. Our new CEO says rounding up is bad for business and we want to redefine round to call floor. Now 5.7.round always returns 5. This is clearly a double-edged sword. You want to open classes for extension, not for modification as we&amp;#x2019;ve done here. This violates the OCP
  67. lets reopen the Float class, and maybe our app doesn&amp;#x2019;t want to round up ever. Our new CEO says rounding up is bad for business and we want to redefine round to call floor. Now 5.7.round always returns 5. This is clearly a double-edged sword. You want to open classes for extension, not for modification as we&amp;#x2019;ve done here. This violates the OCP
  68. lets reopen the Float class, and maybe our app doesn&amp;#x2019;t want to round up ever. Our new CEO says rounding up is bad for business and we want to redefine round to call floor. Now 5.7.round always returns 5. This is clearly a double-edged sword. You want to open classes for extension, not for modification as we&amp;#x2019;ve done here. This violates the OCP
  69. if we give the method a different name, it wont collide with the round function and break any existing code using it.
  70. if we give the method a different name, it wont collide with the round function and break any existing code using it.
  71. if we give the method a different name, it wont collide with the round function and break any existing code using it.
  72. if we give the method a different name, it wont collide with the round function and break any existing code using it.
  73. if we give the method a different name, it wont collide with the round function and break any existing code using it.
  74. if we give the method a different name, it wont collide with the round function and break any existing code using it.
  75. if we give the method a different name, it wont collide with the round function and break any existing code using it.
  76. strings are objects.
  77. integers are objects
  78. integers are objects
  79. integers are objects
  80. integers are objects
  81. integers are objects
  82. integers are objects
  83. integers are objects
  84. integers are objects
  85. floats are objects
  86. floats are objects
  87. floats are objects
  88. shorthand
  89. Arrays are objects. You can actually do some REALLY cool things with methods that array gives you by default, things you&amp;#x2019;d normally write iterators and custom code for, but before we touch on that, I want to cover a little bit more background on Ruby
  90. Like Array, You don&amp;#x2019;t need to use Hash.new to create a new hash object in Ruby. Using the braces is enough to denote that a hash object should be created
  91. This shows a very common idiom in Ruby; using a hash to imitate Keyword Parameters
  92. In fact, you don&amp;#x2019;t even need to provide the braces, and Ruby still figures out that you are declaring a hash.
  93. Regular Expressions are awesome. You should already be familiar with these as a programmer. If you&amp;#x2019;re not, you&amp;#x2019;re doing a lot of things the hard way. This is even more true in Ruby. Support for Regular expressions is built in, just like array and hash.
  94. Once you have an expression, you can use it with the match operator
  95. Once you have an expression, you can use it with the match operator
  96. Once you have an expression, you can use it with the match operator
  97. Handy with substitution
  98. Handy with substitution
  99. {1}, because of this, {2}, and {3}.
  100. blocks with iteration
  101. blocks with iteration
  102. blocks with iteration
  103. blocks with iteration
  104. &lt;=&gt; is the comparison operator
  105. &lt;=&gt; is the comparison operator
  106. &lt;=&gt; is the comparison operator
  107. &lt;=&gt; is the comparison operator
  108. &lt;=&gt; is the comparison operator
  109. A closure is a block of code that, when run, is executed within the scope it was defined (i.e. local variables are available to the block), even after the function has returned, and its local scope has been destroyed. the local variables remain in existence as part of the closure object. When nothing refers to the closure anymore, it&apos;s garbage collected, and the local variables go away.
  110. A closure is a block of code that, when run, is executed within the scope it was defined (i.e. local variables are available to the block), even after the function has returned, and its local scope has been destroyed. the local variables remain in existence as part of the closure object. When nothing refers to the closure anymore, it&apos;s garbage collected, and the local variables go away.
  111. Now that we know a little bit about blocks, lets go back to array and look at the map() method map iterates the items in the array and calls the block you supply for each item, returning a new array with the results
  112. Now that we know a little bit about blocks, lets go back to array and look at the map() method map iterates the items in the array and calls the block you supply for each item, returning a new array with the results
  113. inject is used for reduction. You reduce the items of an array down to a single value. in this example I&amp;#x2019;m using it for summation
  114. inject is used for reduction. You reduce the items of an array down to a single value. in this example I&amp;#x2019;m using it for summation
  115. inject is used for reduction. You reduce the items of an array down to a single value. in this example I&amp;#x2019;m using it for summation
  116. inject is used for reduction. You reduce the items of an array down to a single value. in this example I&amp;#x2019;m using it for summation
  117. we can use inject to easily add support for summation to the array class. Now every array natively supports .sum. Rails gives you sum and .avg for free
  118. we can use inject to easily add support for summation to the array class. Now every array natively supports .sum. Rails gives you sum and .avg for free
  119. we can use inject to easily add support for summation to the array class. Now every array natively supports .sum. Rails gives you sum and .avg for free
  120. we can use inject to easily add support for summation to the array class. Now every array natively supports .sum. Rails gives you sum and .avg for free
  121. we can use inject to easily add support for summation to the array class. Now every array natively supports .sum. Rails gives you sum and .avg for free
  122. we can use inject to easily add support for summation to the array class. Now every array natively supports .sum. Rails gives you sum and .avg for free
  123. we can use inject to easily add support for summation to the array class. Now every array natively supports .sum. Rails gives you sum and .avg for free
  124. Here I use inject to find the greatest number divisible by two in the array. inject keeps track of the best candidate, and I use a ternary operator to determine if i is a better candidate than my existing best.
  125. Here I use inject to find the greatest number divisible by two in the array. inject keeps track of the best candidate, and I use a ternary operator to determine if i is a better candidate than my existing best.
  126. Here I use inject to find the greatest number divisible by two in the array. inject keeps track of the best candidate, and I use a ternary operator to determine if i is a better candidate than my existing best.
  127. Here I use inject to find the greatest number divisible by two in the array. inject keeps track of the best candidate, and I use a ternary operator to determine if i is a better candidate than my existing best.
  128. I&amp;#x2019;m sure all of you recognize the pattern of creating getters and setters for a class. I have a Car class here on the right with a getter and setter for a color attribute. On the left is the rest of the class with getters and setters for engine, make, and model. lot of repetition. Ruby embraces meta programming, and sets the bar for how we need to re-think what we might otherwise blindly accept as just &amp;#x201C;the way our language works&amp;#x201D;. In this case, the attr_accessor method.
  129. which shortens 33 lines of code down to three! But attr_accessor isn&amp;#x2019;t magic Ruby compiler logic, it&amp;#x2019;s just a method. We can take a look at what that method might look like. Don&amp;#x2019;t worry if this goes over your head, I&amp;#x2019;ll get in to each of the methods here after we see how they&amp;#x2019;re used.
  130. which shortens 33 lines of code down to three! But attr_accessor isn&amp;#x2019;t magic Ruby compiler logic, it&amp;#x2019;s just a method. We can take a look at what that method might look like. Don&amp;#x2019;t worry if this goes over your head, I&amp;#x2019;ll get in to each of the methods here after we see how they&amp;#x2019;re used.
  131. which shortens 33 lines of code down to three! But attr_accessor isn&amp;#x2019;t magic Ruby compiler logic, it&amp;#x2019;s just a method. We can take a look at what that method might look like. Don&amp;#x2019;t worry if this goes over your head, I&amp;#x2019;ll get in to each of the methods here after we see how they&amp;#x2019;re used.
  132. which shortens 33 lines of code down to three! But attr_accessor isn&amp;#x2019;t magic Ruby compiler logic, it&amp;#x2019;s just a method. We can take a look at what that method might look like. Don&amp;#x2019;t worry if this goes over your head, I&amp;#x2019;ll get in to each of the methods here after we see how they&amp;#x2019;re used.
  133. which shortens 33 lines of code down to three! But attr_accessor isn&amp;#x2019;t magic Ruby compiler logic, it&amp;#x2019;s just a method. We can take a look at what that method might look like. Don&amp;#x2019;t worry if this goes over your head, I&amp;#x2019;ll get in to each of the methods here after we see how they&amp;#x2019;re used.
  134. which shortens 33 lines of code down to three! But attr_accessor isn&amp;#x2019;t magic Ruby compiler logic, it&amp;#x2019;s just a method. We can take a look at what that method might look like. Don&amp;#x2019;t worry if this goes over your head, I&amp;#x2019;ll get in to each of the methods here after we see how they&amp;#x2019;re used.
  135. which shortens 33 lines of code down to three! But attr_accessor isn&amp;#x2019;t magic Ruby compiler logic, it&amp;#x2019;s just a method. We can take a look at what that method might look like. Don&amp;#x2019;t worry if this goes over your head, I&amp;#x2019;ll get in to each of the methods here after we see how they&amp;#x2019;re used.
  136. which shortens 33 lines of code down to three! But attr_accessor isn&amp;#x2019;t magic Ruby compiler logic, it&amp;#x2019;s just a method. We can take a look at what that method might look like. Don&amp;#x2019;t worry if this goes over your head, I&amp;#x2019;ll get in to each of the methods here after we see how they&amp;#x2019;re used.
  137. which shortens 33 lines of code down to three! But attr_accessor isn&amp;#x2019;t magic Ruby compiler logic, it&amp;#x2019;s just a method. We can take a look at what that method might look like. Don&amp;#x2019;t worry if this goes over your head, I&amp;#x2019;ll get in to each of the methods here after we see how they&amp;#x2019;re used.
  138. which shortens 33 lines of code down to three! But attr_accessor isn&amp;#x2019;t magic Ruby compiler logic, it&amp;#x2019;s just a method. We can take a look at what that method might look like. Don&amp;#x2019;t worry if this goes over your head, I&amp;#x2019;ll get in to each of the methods here after we see how they&amp;#x2019;re used.
  139. which shortens 33 lines of code down to three! But attr_accessor isn&amp;#x2019;t magic Ruby compiler logic, it&amp;#x2019;s just a method. We can take a look at what that method might look like. Don&amp;#x2019;t worry if this goes over your head, I&amp;#x2019;ll get in to each of the methods here after we see how they&amp;#x2019;re used.
  140. which shortens 33 lines of code down to three! But attr_accessor isn&amp;#x2019;t magic Ruby compiler logic, it&amp;#x2019;s just a method. We can take a look at what that method might look like. Don&amp;#x2019;t worry if this goes over your head, I&amp;#x2019;ll get in to each of the methods here after we see how they&amp;#x2019;re used.
  141. which shortens 33 lines of code down to three! But attr_accessor isn&amp;#x2019;t magic Ruby compiler logic, it&amp;#x2019;s just a method. We can take a look at what that method might look like. Don&amp;#x2019;t worry if this goes over your head, I&amp;#x2019;ll get in to each of the methods here after we see how they&amp;#x2019;re used.
  142. which shortens 33 lines of code down to three! But attr_accessor isn&amp;#x2019;t magic Ruby compiler logic, it&amp;#x2019;s just a method. We can take a look at what that method might look like. Don&amp;#x2019;t worry if this goes over your head, I&amp;#x2019;ll get in to each of the methods here after we see how they&amp;#x2019;re used.
  143. introspection
  144. this gives you access to variables the class author might not have exposed.
  145. Every object responds to instance_variables. Here we ask the Gem class from rubygems what instance variables it has defined internally. After it responds, we can query it for the value stored in any of those instance variables as if we had direct access to them.
  146. every object responds to the .constants method. We can ask the Math module what constants it has defined. We can test them directly and see that they are in fact defined, and their values, but we can also request them by string, programatically. We can also set constants programmatically, as well as ask the class or module if they are defined, and even more weirdness with const_missing
  147. inspect sums up my look at introspection. Every object in ruby responds to inspect with a string that describes the data the object holds, which, among other things, is handy for debugging
  148. You&amp;#x2019;ve already seen define_method, it&amp;#x2019;s what made attr_accessor work.
  149. but what happens when we want to implement div, span, anchors, unordered lists, etc?
  150. First lets define a constant to hold all our tag types
  151. There&amp;#x2019;s a really handy syntax for writing arrays of strings with a single word each, it&amp;#x2019;s %w()
  152. before we go on, I&amp;#x2019;m going to switch the syntax I&amp;#x2019;m using to define class methods. instead of self.method_name I&amp;#x2019;m using this class &lt;&lt; self pattern which is going to help keep things clean.
  153. now instead of defining the strong method ourselves, lets change that to iterate the TAG_TYPES array and define each method.
  154. Now we have all these methods defined for free. If we later add support for list items, we don&amp;#x2019;t have to add a method for it, we just add it to the TAG_TYPES array and the class automatically knows how to handle this.
  155. Another way you can do this is with method_missing. Don&amp;#x2019;t even define the methods, just respond when they&amp;#x2019;re called.
  156. In fact, why even have a list of supported tags at all? Now there&amp;#x2019;s nothing to change to support new tags
  157. You get really cool code. What does this remind you of? It&amp;#x2019;s starting to look more and more like we created something that can generate XML for us. And in fact, that&amp;#x2019;s exactly the premise behind the Builder gem package authored by Jim Weirich.
  158. But there&amp;#x2019;s a problem in using a class to generate xml that can use any tag name. Object already defines a ton of methods that if you try to call, will never hit method_missing, methods like new, id, send, freeze, class, and &amp;#x201C;methods&amp;#x201D;, and any class you define must descend from Object. Clearly, we need more magic.
  159. But there&amp;#x2019;s a problem in using a class to generate xml that can use any tag name. Object already defines a ton of methods that if you try to call, will never hit method_missing, methods like new, id, send, freeze, class, and &amp;#x201C;methods&amp;#x201D;, and any class you define must descend from Object. Clearly, we need more magic.
  160. But there&amp;#x2019;s a problem in using a class to generate xml that can use any tag name. Object already defines a ton of methods that if you try to call, will never hit method_missing, methods like new, id, send, freeze, class, and &amp;#x201C;methods&amp;#x201D;, and any class you define must descend from Object. Clearly, we need more magic.
  161. Meet undef_method. Care to take a guess what this does?
  162. Now, you might expect Html.methods to return an empty array now, *click*
  163. buuut, we undefined it. *pause* So there&amp;#x2019;s no more dot-methods method in our class. Practically speaking, there&amp;#x2019;s a couple methods you don&amp;#x2019;t want to undefine, but lets just gloss over that.
  164. With Builder you create a new builder object, in this example it&amp;#x2019;s called &amp;#x2018;xml&amp;#x2019;. the methods you call on it become your tags. Blocks automatically nest tags within other tags.
  165. And your output looks awesome. Life. is. good.
  166. No, I&amp;#x2019;m not talking about restricting instantiation of a class to a single object.
  167. A common use for singleton methods would be for designing a GUI; A button is a button is a button, but you don&amp;#x2019;t want each instance of a button to do the same thing. Singleton methods let us define or redefine instance methods on the fly for a single object.
  168. A common use for singleton methods would be for designing a GUI; A button is a button is a button, but you don&amp;#x2019;t want each instance of a button to do the same thing. Singleton methods let us define or redefine instance methods on the fly for a single object.
  169. A common use for singleton methods would be for designing a GUI; A button is a button is a button, but you don&amp;#x2019;t want each instance of a button to do the same thing. Singleton methods let us define or redefine instance methods on the fly for a single object.
  170. A common use for singleton methods would be for designing a GUI; A button is a button is a button, but you don&amp;#x2019;t want each instance of a button to do the same thing. Singleton methods let us define or redefine instance methods on the fly for a single object.
  171. A common use for singleton methods would be for designing a GUI; A button is a button is a button, but you don&amp;#x2019;t want each instance of a button to do the same thing. Singleton methods let us define or redefine instance methods on the fly for a single object.
  172. A common use for singleton methods would be for designing a GUI; A button is a button is a button, but you don&amp;#x2019;t want each instance of a button to do the same thing. Singleton methods let us define or redefine instance methods on the fly for a single object.
  173. A common use for singleton methods would be for designing a GUI; A button is a button is a button, but you don&amp;#x2019;t want each instance of a button to do the same thing. Singleton methods let us define or redefine instance methods on the fly for a single object.
  174. A common use for singleton methods would be for designing a GUI; A button is a button is a button, but you don&amp;#x2019;t want each instance of a button to do the same thing. Singleton methods let us define or redefine instance methods on the fly for a single object.
  175. eval - evaluates code, typically class_eval - evaluates code in the context of the object&amp;#x2019;s class, or metaclass instance_eval - evals code in the context of the object, module_eval - evals in context of a module
  176. One day a specific client said to me, &amp;#x201C;These records should never get destroyed, ever. I want something in place to prevent them from being destroyed&amp;#x201D;. So, mixing the use of module_eval and the concept of creating a DSL, I came up with this patch. I reopen the ActiveRecord::Associations::ClassMethods module, which is part of Rails, and I define a class method called refuse_to_destroy!.
  177. Now I have a DSL I can write in my models that tells it how to act. User.destroy now raises an exception
  178. it works by evaluating the code in the User class and adds a before_destory hook on the ActiveRecord model.
  179. I had this idiom in another language I came from, that essentially lets you temporarily change the scope. But when I came to Ruby, it just didn&amp;#x2019;t exist.
  180. But it turns out you can achieve something similar with instance_eval, since it changes the scope while the block executes. Cool, but it doesn&amp;#x2019;t read as nice as that &amp;#x201C;with&amp;#x201D; command in my old language. But this is ruby, and you can make anything work the way you want it to!
  181. We can add a with method to the Object class, which makes it available everywhere. We&amp;#x2019;ll set it up to take an object and a block of code as parameters, then call instance_eval on the object to change the scope to that object, and pass the block along to instance_eval, which will execute it in the object&amp;#x2019;s scope.
  182. Now I have the syntax and method I was familiar with from the old language, implemented in Ruby. The great thing about this is there really is not a lot of limits on what you can do. You could almost create your own programming language or script, and execute it as if it&amp;#x2019;s ruby code using instance_eval
  183. There&amp;#x2019;s already some really cool projects that take advantage of this. Cucumber actually executes english text as if it&amp;#x2019;s code
  184. really common in Ruby
  185. railsy
  186. almost all operators in ruby... are methods!
  187. almost all operators in ruby... are methods!
  188. almost all operators in ruby... are methods!
  189. almost all operators in ruby... are methods!
  190. My favorite kind of proxy is by far the spy proxy, though there are many uses for an object proxy (adding an optional layer of logic to a class, such as access control, for example, without modifying the class).
  191. My favorite kind of proxy is by far the spy proxy, though there are many uses for an object proxy (adding an optional layer of logic to a class, such as access control, for example, without modifying the class).
  192. My favorite kind of proxy is by far the spy proxy, though there are many uses for an object proxy (adding an optional layer of logic to a class, such as access control, for example, without modifying the class).
  193. My favorite kind of proxy is by far the spy proxy, though there are many uses for an object proxy (adding an optional layer of logic to a class, such as access control, for example, without modifying the class).
  194. My favorite kind of proxy is by far the spy proxy, though there are many uses for an object proxy (adding an optional layer of logic to a class, such as access control, for example, without modifying the class).
  195. My favorite kind of proxy is by far the spy proxy, though there are many uses for an object proxy (adding an optional layer of logic to a class, such as access control, for example, without modifying the class).
  196. My favorite kind of proxy is by far the spy proxy, though there are many uses for an object proxy (adding an optional layer of logic to a class, such as access control, for example, without modifying the class).
  197. My favorite kind of proxy is by far the spy proxy, though there are many uses for an object proxy (adding an optional layer of logic to a class, such as access control, for example, without modifying the class).
  198. My favorite kind of proxy is by far the spy proxy, though there are many uses for an object proxy (adding an optional layer of logic to a class, such as access control, for example, without modifying the class).
  199. My favorite kind of proxy is by far the spy proxy, though there are many uses for an object proxy (adding an optional layer of logic to a class, such as access control, for example, without modifying the class).
  200. duck typing, looks like a duck, quacks like a duck, we don&amp;#x2019;t care. ppl objects are interacting with our bmw differently
  201. duck typing, looks like a duck, quacks like a duck, we don&amp;#x2019;t care. ppl objects are interacting with our bmw differently
  202. duck typing, looks like a duck, quacks like a duck, we don&amp;#x2019;t care. ppl objects are interacting with our bmw differently
  203. duck typing, looks like a duck, quacks like a duck, we don&amp;#x2019;t care. ppl objects are interacting with our bmw differently
  204. duck typing, looks like a duck, quacks like a duck, we don&amp;#x2019;t care. ppl objects are interacting with our bmw differently
  205. duck typing, looks like a duck, quacks like a duck, we don&amp;#x2019;t care. ppl objects are interacting with our bmw differently
  206. duck typing, looks like a duck, quacks like a duck, we don&amp;#x2019;t care. ppl objects are interacting with our bmw differently
  207. duck typing, looks like a duck, quacks like a duck, we don&amp;#x2019;t care. ppl objects are interacting with our bmw differently
  208. lets say we have a method that does two things. the first it does very very slowly (perhaps, reading through 10 million database records to get the record count) the second it does much faster (finding a specific record). Now, in my experience with mysql, offset isn&amp;#x2019;t really that fast either, but lets call it negligible.
  209. lets say we have a method that does two things. the first it does very very slowly (perhaps, reading through 10 million database records to get the record count) the second it does much faster (finding a specific record). Now, in my experience with mysql, offset isn&amp;#x2019;t really that fast either, but lets call it negligible.
  210. lets say we have a method that does two things. the first it does very very slowly (perhaps, reading through 10 million database records to get the record count) the second it does much faster (finding a specific record). Now, in my experience with mysql, offset isn&amp;#x2019;t really that fast either, but lets call it negligible.
  211. lets say we have a method that does two things. the first it does very very slowly (perhaps, reading through 10 million database records to get the record count) the second it does much faster (finding a specific record). Now, in my experience with mysql, offset isn&amp;#x2019;t really that fast either, but lets call it negligible.
  212. lets say we have a method that does two things. the first it does very very slowly (perhaps, reading through 10 million database records to get the record count) the second it does much faster (finding a specific record). Now, in my experience with mysql, offset isn&amp;#x2019;t really that fast either, but lets call it negligible.
  213. There are other ways to solve this problem, like making user count an instance variable and using the &amp;#x201C;or equals&amp;#x201D; meme (meam) you see here, which only evaluates the code on the right and sets user count if user count is nil or false. But lets ignore that, too.
  214. class_eval lets us evaluate the block of code as if we were running it inside the class, and not the current method. define_method takes a block, which it turns in to a closure--meaning it keeps a reference to the local variable user_count, so it doesn&amp;#x2019;t drop out of scope and get freed
  215. class_eval lets us evaluate the block of code as if we were running it inside the class, and not the current method. define_method takes a block, which it turns in to a closure--meaning it keeps a reference to the local variable user_count, so it doesn&amp;#x2019;t drop out of scope and get freed
  216. class_eval lets us evaluate the block of code as if we were running it inside the class, and not the current method. define_method takes a block, which it turns in to a closure--meaning it keeps a reference to the local variable user_count, so it doesn&amp;#x2019;t drop out of scope and get freed
  217. class_eval lets us evaluate the block of code as if we were running it inside the class, and not the current method. define_method takes a block, which it turns in to a closure--meaning it keeps a reference to the local variable user_count, so it doesn&amp;#x2019;t drop out of scope and get freed
  218. class_eval lets us evaluate the block of code as if we were running it inside the class, and not the current method. define_method takes a block, which it turns in to a closure--meaning it keeps a reference to the local variable user_count, so it doesn&amp;#x2019;t drop out of scope and get freed
  219. class_eval lets us evaluate the block of code as if we were running it inside the class, and not the current method. define_method takes a block, which it turns in to a closure--meaning it keeps a reference to the local variable user_count, so it doesn&amp;#x2019;t drop out of scope and get freed
  220. class_eval lets us evaluate the block of code as if we were running it inside the class, and not the current method. define_method takes a block, which it turns in to a closure--meaning it keeps a reference to the local variable user_count, so it doesn&amp;#x2019;t drop out of scope and get freed
  221. class_eval lets us evaluate the block of code as if we were running it inside the class, and not the current method. define_method takes a block, which it turns in to a closure--meaning it keeps a reference to the local variable user_count, so it doesn&amp;#x2019;t drop out of scope and get freed
  222. class_eval lets us evaluate the block of code as if we were running it inside the class, and not the current method. define_method takes a block, which it turns in to a closure--meaning it keeps a reference to the local variable user_count, so it doesn&amp;#x2019;t drop out of scope and get freed
  223. class_eval lets us evaluate the block of code as if we were running it inside the class, and not the current method. define_method takes a block, which it turns in to a closure--meaning it keeps a reference to the local variable user_count, so it doesn&amp;#x2019;t drop out of scope and get freed
  224. after the first time the method runs, it redefines itself to something like this. The method has both rewritten itself and accomplished a form of caching at the same time. self-optimization-code similar to this is used by Rails internally for routing. The first time the method is called it generates its own routing methods based on a more complete picture of what&amp;#x2019;s required and cuts out a lot of dead cycles that would otherwise check routes that are never used.
  225. If you&amp;#x2019;re liking the Ruby vibe and you want to get in to it a little more, you&amp;#x2019;ll want to make a note to visit some of these sites.
  226. Ruby screencasts