SlideShare a Scribd company logo
1 of 244
Tasty Burgers
ZOMG GOOD
 MORNING!
HAPPY
WEDNESDAY!
PEW PEW PEW!
http://tenderlovemaking.com/
       railsconf2010.pdf
Aaron Patterson
@tenderlove
Seattle.rb
Ruby-Core Team
AT&T, AT&T logo and all AT&T related marks are trademarks of AT&T Intellectual Property and/or AT&T affiliated companies.
We’re Hiring!
Rails 4*
Rails 4*

• Ponies
• Unicorns
• Venture Capital
*Disclaimer



Some of the things I say may not be true.
Why I’m Here*
*The following events may not have actually
                 happened
One Day...
I
was
out
jogging
Hello! This is
@tenderlove,
who is this?
This is Chad
  Fowler!
AH! Chad
Flower, the
  famous
  florist?
Famous Florist: Chad Flower
No.
Chad Fouler
the Baseball
  player?
Baseball Player: Chad Fouler
No.
Chad
  Flounder the
Fish Whisperer?
Fish Whisperer: Chad Flounder
No.
Wait. Yes this is
Chad Flounder,
Fish Whisperer.
But I'm calling on
behalf of Chad Fowler,
 Ruby Programmer.
To invite you to
  RailsConf.
I accept.
Nom.
The Next Day
At Work
I'll need your bio, affiliation, and
so on. I would also love a recent
  head shot of you. 300 dpi, 3 "
      minimum is preferable.
Professional
2 min later...
Erm. Nice mullet. Is
  that really you?
Yes
You know that means I'm
 going to require you to
   have that mullet at
       RailsConf.
Time to get
Professional
Rails
This is RailsConf right?
Ingredients
ERb
SQLITE         RACK
       RAILS
YAML
Using our
Ingredients
Twisting Software
FEAR
CONFUSION
INTRIGUE
INSPIRED
Better ingredients,
 better burgers.
   Guaranteed
TOPICS OF DOOM

• SQLite
• ERb
• Rack
• YAML
SQLite3-Ruby
SQLite3-Ruby

• Adapter for SQLite3 database
• Originally by Jamis Buck
• SWIG
Relationship with
      Rails
Default Database
class Foo < AR::Base; end

Foo.find(:all, :conditions => {...})

Foo.find(:all, :conditions => [
  ‘x = ?’, 20
])
ActionView


ActionController


 ActiveRecord


 SQLite3-Ruby
ActiveRecord
SQLite3-Ruby
AR::Base       SQLite3 Adapter



Connection Pool
SQLite3Adapter



SQLite3-Ruby
Outside Rails
Establishing a
           Connection

require 'sqlite3'

connection =
 SQLite3::Database.new('file.sqlite3')
In Memory
               Database
                                     Pro Tip


require 'sqlite3'

connection =
 SQLite3::Database.new(':memory:')
In Memory
               Database
                                     Pro Tip


require 'sqlite3'

connection =
 SQLite3::Database.new(':memory:')
database.yml


development:
 adapter: sqlite3
 database: ':memory:'
Making a Query


connection.execute('CREATE TABLE foo(id INTEGER)')


connection.execute('INSERT INTO foo (id) VALUES (?)',
[10])
Preparing a Statement

stmt = connection.prepare('SELECT * FROM foo WHERE id
= ?')

stmt.bind_param(1, 10)

stmt.each do |row|
 p row
end
Why Prepare a
 Statement?
Statements can be
     cached
Can improve
 database
performance
Rails Caveats
Parameter Substitution
User.find(10)
SELECT * FROM users WHERE id = ?
stmt = get_cached_stmt ||
 connection.prepare(
   'SELECT * FROM users WHERE id = ?'
 )
stmt.execute(10)
WRONG
stmt = get_cached_stmt ||
 connection.prepare(
   'SELECT * FROM users WHERE id = ?'
 )
stmt.execute(10)
connection.execute(
  'SELECT * FROM users WHERE id = 10'
)
No Prepared
Statement Support
        :-(
Room for Improvement?
Twisting SQLite3
• Step 1: Read the API
• Step 2: Write your code
• Step 3: Annoy your friends (or profit)
Step 1: Read the API
struct sqlite3_vfs {
  int iVersion;        /* Structure version number */
  int szOsFile;         /* Size of subclassed sqlite3_file */
  int mxPathname;           /* Maximum file pathname length */
  sqlite3_vfs *pNext;      /* Next registered VFS */
  const char *zName;         /* Name of this virtual file system */
  void *pAppData;          /* Pointer to application-specific data */
  int (*xOpen)(sqlite3_vfs*, const char *zName, sqlite3_file*,
           int flags, int *pOutFlags);
  int (*xDelete)(sqlite3_vfs*, const char *zName, int syncDir);
  int (*xAccess)(sqlite3_vfs*, const char *zName, int flags, int *pResOut);
  int (*xFullPathname)(sqlite3_vfs*, const char *zName, int nOut, char *zOut);
  void *(*xDlOpen)(sqlite3_vfs*, const char *zFilename);
  void (*xDlError)(sqlite3_vfs*, int nByte, char *zErrMsg);
  void (*(*xDlSym)(sqlite3_vfs*,void*, const char *zSymbol))(void);
  void (*xDlClose)(sqlite3_vfs*, void*);
  int (*xRandomness)(sqlite3_vfs*, int nByte, char *zOut);
  int (*xSleep)(sqlite3_vfs*, int microseconds);
  int (*xCurrentTime)(sqlite3_vfs*, double*);
  int (*xGetLastError)(sqlite3_vfs*, int, char *);
  /* New fields may be appended in figure versions. The iVersion
  ** value will increment whenever this happens. */
};
IO Hooks
Step 2: Write our Code
static int rbFile_close(sqlite3_file * ctx)
{
  rubyFilePtr rfile = (rubyFilePtr)ctx;
  VALUE file = rfile->file;
  rb_funcall(file, rb_intern("close"), 0);
  return SQLITE_OK;
}
class VFS < SQLite3::VFS
 def open(name, flags)
   OurFile.new(name, flags)
 end
end

class OurFile
 def read(...); ... end
 def write(...); ... end
end
Anything can store
a SQLite Database
__END__ + DATA
class EvilVFS < SQLite3::VFS
 def open name, flags
   DATABase.new name, flags
 end
end

class DATABase < SQLite3::VFS::File
 def initialize name, flags
   super
   @store = File.open(name, File::RDWR | File::CREAT)
   @offset = 0

  if File.expand_path(__FILE__) == name
    @store.seek DATA.pos
    @offset = DATA.pos
  end
 end

 def close
  @store.close
 end

 def read amt, offset
  @store.seek(offset + @offset)
  @store.read amt
 end

 def write data, offset
  @store.seek(offset + @offset)
  @store.write data
 end

 def sync opts
  @store.fsync
 end

 def file_size
SQLite3.vfs_register(EvilVFS.new)
db = SQLite3::Database.new(__FILE__, nil, 'EvilVFS')

db.execute(<<-eosql)
 create table if not exists
 users(id integer primary key, name string)
eosql

100.times {
  db.execute(<<-eosql, 'tenderlove')
   insert into users(name) values (?)
  eosql
}

p db.execute('select count(*) from users')

__END__
Step 3: Profit?
Get the Code!
http://gist.github.com/319224/
What's New in
SQLite3-Ruby?
Fun Stuff!!


• Ruby 1.9 Encoding support
• 1000x faster (or something)
Encodings
require 'sqlite3'

db = SQLite3::Database.new(':memory:')

db.execute('CREATE TABLE foo(id INTEGER, name VARCHAR)')
db.execute('INSERT INTO foo (id, name) VALUES (?,?)',[10,'hello
world'])

rows = db.execute('SELECT name FROM foo')
p rows.first.first.encoding # => #<Encoding:UTF-8>

Encoding.default_internal = 'EUC-JP'

rows = db.execute('SELECT name FROM foo')
p rows.first.first.encoding # => #<Encoding:EUC-JP>
Encodings
require 'sqlite3'

db = SQLite3::Database.new(':memory:')

db.execute('CREATE TABLE foo(id INTEGER, name VARCHAR)')
db.execute('INSERT INTO foo (id, name) VALUES (?,?)',[10,'hello
world'])

rows = db.execute('SELECT name FROM foo')
p rows.first.first.encoding # => #<Encoding:UTF-8>

Encoding.default_internal = 'EUC-JP'

rows = db.execute('SELECT name FROM foo')
p rows.first.first.encoding # => #<Encoding:EUC-JP>
Encodings
require 'sqlite3'

db = SQLite3::Database.new(':memory:')

db.execute('CREATE TABLE foo(id INTEGER, name VARCHAR)')
db.execute('INSERT INTO foo (id, name) VALUES (?,?)',[10,'hello
world'])

rows = db.execute('SELECT name FROM foo')
p rows.first.first.encoding # => #<Encoding:UTF-8>

Encoding.default_internal = 'EUC-JP'

rows = db.execute('SELECT name FROM foo')
p rows.first.first.encoding # => #<Encoding:EUC-JP>
Speed! (on selects)
                    1.2.5             1.3.0

1000

 100

  10

   1

 0.1

0.01
       500   1000     1500   2000   2500      3000   3500
ERb
ERb

• Masatoshi SEKI
• Template System
• Ruby 1.8 and 1.9
Relationship with
      Rails
app/views/**/*.html.erb
render('users/show')
Template Registration
class Something::ERB < AV::Template::Handler
 def render(template, *args)
   ...
   body
 end
end

ActionView::Template.register_template_handler(
  :erb, Something::ERB
)
AV Resolver
           render()


Something::ERB
Something::ERB



     ERb
Outside Rails
require 'erb'

erb = ERB.new(File.read(__FILE__))
puts erb.result(binding)

__END__
Hello world! <%= 10 + 100 %>
Output

require 'erb'

erb = ERB.new(File.read(__FILE__))
puts erb.result(binding)

__END__
Hello world! 110
Output

require 'erb'

erb = ERB.new(File.read(__FILE__))
puts erb.result(binding)

__END__
Hello world! 110
require 'erb'

erb = ERB.new(File.read(__FILE__))
puts erb.result(binding)

__END__
Hello world! <%= 10 + 100 %>
Template Source

require 'erb'

erb = ERB.new(File.read(__FILE__))
puts erb.src

__END__
Hello world! <%= 10 + 100 %>
Template Source

require 'erb'

erb = ERB.new(File.read(__FILE__))
puts erb.src

__END__
Hello world! <%= 10 + 100 %>
Output
_erbout = ''; _erbout.concat "require 'erb'nnerb
= ERB.new(File.read(__FILE__))nputs erb.srcn
n__END__nHello world! "




; _erbout.concat(( 10 + 100 ).to_s);
_erbout.concat "n"
; _erbout
Output Buffer

require 'erb'

erb = ERB.new(File.read(__FILE__), nil, nil, '@foo')
puts erb.src

__END__
Hello world! <%= 10 + 100 %>
Output Buffer

require 'erb'

erb = ERB.new(File.read(__FILE__), nil, nil, '@foo')
puts erb.src

__END__
Hello world! <%= 10 + 100 %>
Output
@foo = ''; @foo.concat "require 'erb'nnerb =
ERB.new(File.read(__FILE__), nil, nil, '@foo')nputs
erb.srcnn__END__nHello world! "




; @foo.concat(( 10 + 100 ).to_s); @foo.concat
"n"
; @foo
Output
@foo = ''; @foo.concat "require 'erb'nnerb =
ERB.new(File.read(__FILE__), nil, nil, '@foo')nputs
erb.srcnn__END__nHello world! "




; @foo.concat(( 10 + 100 ).to_s); @foo.concat
"n"
; @foo
Twisting ERb
ERb Memory
 Footprint
IO Input
mmap
allocate memory, or map files or devices into
                 memory
gem install mmap
Mmap.new(__FILE__)
IO input
require 'erb'
require 'rubygems'
require 'mmap'

erb = ERB.new(Mmap.new(__FILE__), nil, nil, '@foo')
erb.result(binding)

puts @foo

__END__
Hello world! <%= 10 + 100 %>
IO Output
Our Problem

def set_eoutvar(compiler, eoutvar)
 ...
 cmd = []
 cmd.push "#{eoutvar} = ''"

 compiler.pre_cmd = cmd
 ...
end
Our Problem

def set_eoutvar(compiler, eoutvar)
 ...
 cmd = []
 cmd.push "#{eoutvar} = ''"

 compiler.pre_cmd = cmd
 ...
end
A Solution


class ERB::Compiler
 def pre_cmd= x; end
end
Source Output (before)
@foo = ''; @foo.concat "require 'erb'nrequire
'rubygems'nrequire 'mmap'nnclass
ERB::Compilern def pre_cmd= x; endnend
nnerb = ERB.new(Mmap.new(__FILE__), nil,
nil, '@foo')nputs erb.srcnn__END__nHello
world! "

; @foo.concat(( 10 + 100 ).to_s); @foo.concat
"n"
; @foo
Source Output (after)
@foo.concat "require 'erb'nrequire
'rubygems'nrequire 'mmap'nnclass
ERB::Compilern def pre_cmd= x; endnend
nnerb = ERB.new(Mmap.new(__FILE__), nil,
nil, '@foo')nputs erb.srcnn__END__nHello
world! "

; @foo.concat(( 10 + 100 ).to_s); @foo.concat
"n"
; @foo
Source Output (before)
@foo = ''; @foo.concat "require 'erb'nrequire
'rubygems'nrequire 'mmap'nnclass
ERB::Compilern def pre_cmd= x; endnend
nnerb = ERB.new(Mmap.new(__FILE__), nil,
nil, '@foo')nputs erb.srcnn__END__nHello
world! "

; @foo.concat(( 10 + 100 ).to_s); @foo.concat
"n"
; @foo
Source Output
@foo.concat "require 'erb'nrequire
'rubygems'nrequire 'mmap'nnclass
ERB::Compilern def pre_cmd= x; endnend
nnerb = ERB.new(Mmap.new(__FILE__), nil,
nil, '@foo')nputs erb.srcnn__END__nHello
world! "

; @foo.concat(( 10 + 100 ).to_s); @foo.concat
"n"
; @foo
Adapting to "concat"


class IOAdapter < Struct.new(:io)
 def concat(string)
   io.write string
 end
end
require 'erb'
require 'mmap'

class ERB::Compiler
 def pre_cmd= x; end
end

class IOAdapter < Struct.new(:io)
 def concat(string)
   io.write string
 end
end

@foo = IOAdapter.new($stdout)

erb = ERB.new(Mmap.new(__FILE__), nil, nil, '@foo')
erb.result(binding)

__END__
Hello world! <%= 10 + 100 %>
Performance Results*


• Slower compiler
• Similar output
• Lower memory overhead
*YMMV
  :-(
rack
Ruby webserver interface ACK!
not racc
Ryet Another Compiler Compiler
Rack


• Interface between app code and
  servers

• By Christian Neukirchen
Relationship with
      Rails
Unicorn (etc)

   Rack

    Rails
Unicorn (etc)

   Rack

Rack Adapter
   RAILS
SLIDE MISSING
Rack Outside Rails
Handler#call(env)
class MyRack
 def call env
   [
     200,
     {'X-RailsConf' => 'yay'},
     "hello world!"
   ]
 end
end
HTTP/1.1 200 OK
Connection: close
Date: Thu, 03 Jun 2010 03:57:05 GMT
Server: WEBrick/1.3.1 (Ruby/
1.8.7/2009-06-08)
Content-Length: 11
X-Railsconf: yay

hello world
HTTP/1.1 200 OK
Connection: close
Date: Thu, 03 Jun 2010 03:57:05 GMT
Server: WEBrick/1.3.1 (Ruby/
1.8.7/2009-06-08)
Content-Length: 11
X-Railsconf: yay

hello world
body#each(&blk)
block must yield a
      String
class MyRack
 def call env
   [
     200,
     {'X-RailsConf' => 'yay'},
     ['hello ', 'America!']
   ]
 end
end
GET / HTTP/1.0

HTTP/1.1 200 OK
Connection: close
Date: Thu, 03 Jun 2010 04:06:08 GMT
Server: WEBrick/1.3.1 (Ruby/
1.8.7/2009-06-08)
Content-Length: 14
X-Railsconf: yay

hello America!
body#close
class MyRack
 def call env
   [
     200,
     {'X-RailsConf' => 'yay'},
     File.open(__FILE__, 'rb')
   ]
 end
end
HTTP/1.1 200 OK
Connection: close
Date: Thu, 03 Jun 2010 04:08:21 GMT
Server: WEBrick/1.3.1 (Ruby/1.8.7/2009-06-08)
Content-Length: 215
X-Railsconf: yay

class MyRack
 def call env
   [
     200,
     {'X-RailsConf' => 'yay'},
     File.open(__FILE__, 'rb')
   ]
 end
end
Great Flexibility
Twisting Rack
ERB Handler
class ERBHandler
 def initialize
   @root =
    File.join(File.dirname(__FILE__), 'htdocs')
 end

 def call env
  erb =
    ERB.new(File.read("#{@root}#{env['REQUEST_PATH']}"))
  [
    200,
    {'X-RailsConf' => 'yay'},
    erb.result(binding)
  ]
 end
end
<%= env['SERVER_SOFTWARE'] %>

<%
 def fib n
  n < 2 ? n : fib(n - 1) + fib(n - 2)
 end
%>
<% 1.upto(30) do |i| %>
 <%= fib(i) %>
<% end %>
Connection Times (ms)
         min mean[+/-sd] median max
Connect:     0 0 0.0     0    0
Processing: 3239 3312 91.8 3274 3483
Waiting:   3238 3311 91.2 3274 3482
Total:    3239 3312 91.8 3274 3483
Requests per second: 0.30 [#/sec] (mean)
Time per request:   3312.112 [ms] (mean)
Template Caching
class ERBHandler
 def initialize
   @root = File.join(File.dirname(__FILE__), 'htdocs')
   @cache = Hash.new do |h,file|
    h[file] = ERB.new(File.read("#{@root}#{file}"))
   end
 end

 def call env
  [
    200,
    {'X-RailsConf' => 'yay'},
    @cache[env['REQUEST_PATH']].result(binding)
  ]
 end
end
class ERBHandler
 def initialize
   @root = File.join(File.dirname(__FILE__), 'htdocs')
   @cache = Hash.new do |h,file|
    h[file] = ERB.new(File.read("#{@root}#{file}"))
   end
 end

 def call env
  [
    200,
    {'X-RailsConf' => 'yay'},
    @cache[env['REQUEST_PATH']].result(binding)
  ]
 end
end
Connection Times (ms)
         min mean[+/-sd] median max
Connect:     0 0 0.0     0    0
Processing: 3230 3267 30.6 3269 3315
Waiting:   3229 3267 30.5 3269 3315
Total:    3230 3267 30.7 3269 3315
Requests per second: 0.31 [#/sec] (mean)
Time per request:   3266.990 [ms] (mean)
Leverage "each"
rd, wr = IO.pipe
ERB Hacks

class ERB::Compiler
 def pre_cmd= x; end
end

class IO
 alias :concat :write
end
class ERBHandler
 def initialize
   @root = File.join(File.dirname(__FILE__), 'htdocs')
   @cache = Hash.new do |h,file|
    h[file] = ERB.new(
     File.read("#{@root}#{file}"), nil, nil, 'wr')
   end
 end

 def call env
  rd, wr = IO.pipe

  Thread.new do
   @cache[env['REQUEST_PATH']].result(binding)
   wr.close
  end

  [ 200, {'X-RailsConf' => 'yay'}, rd ]
 end
end
class ERBHandler
 def initialize
   @root = File.join(File.dirname(__FILE__), 'htdocs')
   @cache = Hash.new do |h,file|
    h[file] = ERB.new(
     File.read("#{@root}#{file}"), nil, nil, 'wr')
   end
 end

 def call env
  rd, wr = IO.pipe

  Thread.new do
   @cache[env['REQUEST_PATH']].result(binding)
   wr.close
  end

  [ 200, {'X-RailsConf' => 'yay'}, rd ]
 end
end
class ERBHandler
 def initialize
   @root = File.join(File.dirname(__FILE__), 'htdocs')
   @cache = Hash.new do |h,file|
    h[file] = ERB.new(
     File.read("#{@root}#{file}"), nil, nil, 'wr')
   end
 end

 def call env
  rd, wr = IO.pipe

  Thread.new do
   @cache[env['REQUEST_PATH']].result(binding)
   wr.close
  end

  [ 200, {'X-RailsConf' => 'yay'}, rd ]
 end
end
class ERBHandler
 def initialize
   @root = File.join(File.dirname(__FILE__), 'htdocs')
   @cache = Hash.new do |h,file|
    h[file] = ERB.new(
     File.read("#{@root}#{file}"), nil, nil, 'wr')
   end
 end

 def call env
  rd, wr = IO.pipe

  Thread.new do
   @cache[env['REQUEST_PATH']].result(binding)
   wr.close
  end

  [ 200, {'X-RailsConf' => 'yay'}, rd ]
 end
end
class ERBHandler
 def initialize
   @root = File.join(File.dirname(__FILE__), 'htdocs')
   @cache = Hash.new do |h,file|
    h[file] = ERB.new(
     File.read("#{@root}#{file}"), nil, nil, 'wr')
   end
 end

 def call env
  rd, wr = IO.pipe

  Thread.new do
   @cache[env['REQUEST_PATH']].result(binding)
   wr.close
  end

  [ 200, {'X-RailsConf' => 'yay'}, rd ]
 end
end
Connection Times (ms)
         min mean[+/-sd] median max
Connect:     0 0 0.0     0    0
Processing: 3273 3312 22.0 3322 3338
Waiting:    0 1 0.5     0    2
Total:    3273 3313 22.0 3322 3338
Connection Times (ms)
         min mean[+/-sd] median max
Connect:     0 0 0.0     0    0
Processing: 3273 3312 22.0 3322 3338
Waiting:    0 1 0.5     0    2
Total:    3273 3313 22.0 3322 3338
Rails Improvements
YAML
Psych and Syck
Syck

• Ruby 1.8 and 1.9
• YAML 1.0 (mostly) parser / emitter
• Written by Why
Psych

• Ruby >= 1.9.2 only
• Wraps libyaml
• YAML 1.1 parser / emitter
• Written by me
Relationship with
      Rails
database.yml

development: &defaults
 adapter: sqlite3
 database: db/development.sqlite3

test:
 <<: *defaults
 database: db/test.sqlite3
i18n
ja:
  calendars:
    gregorian:
     days:
      format:
       abbreviated:
         fri:
       mon:
       sat:
       sun:
       thu:
       tue:
       wed:
fixtures


default:
 user: default
 text: hello world
 created_at: <%= Time.now.to_formatted_s(:db)
%>
Serialized Attributes


# Serialize a preferences attribute
class User < AR::Base
 serialize :preferences # ZOMG YAML!
end
YAML Outside Rails
Parsing YAML
Ruby 1.8 / 1.9


require 'yaml'

YAML.load_file('some_file.yml')
YAML.load('--- hello world!')
Ruby 1.9.2 / Psych


require 'psych'

Psych.load_file('some_file.yml')
Psych.load('--- hello world!')
1.9.2 Opt-in

require 'yaml'

YAML::ENGINE.yamler = 'psych'

YAML.load('--- this is psych')
Dumping YAML
require 'psych'

Psych.dump { :foo => 'bar' }
{ :hello => 'world' }.to_yaml
Dumping JSON?
YAML Map


---
foo: bar
YAML Map


---
'foo': 'bar'
YAML Map


---
{ 'foo': 'bar' }
require 'psych'

Psych.to_json { :foo => 'bar' }
Twisting Psych
Custom Emitter
class Foo
 def initialize
   @greeting = 'world'
 end

 def encode_with(coder)
  coder['hello'] = @greeting
 end

 def init_with(coder)
  @greeting = coder['hello']
 end
end
Psych.dump


--- !ruby/object:Foo
hello: world
Psych.load


#<Foo:0x000001009f6770
@greeting="world">
Format Agnostic
class Foo
 def initialize
   @greeting = 'world'
 end

 def encode_with(coder)
  coder['hello'] = @greeting
 end

 def init_with(coder)
  @greeting = coder['hello']
 end
end
YAML & JSON


Psych.dump Foo.new
Psych.to_json Foo.new
class XMLDumper < Psych::Handler
 def self.dump(object)
   dumper = new
   viz = Psych::Visitors::YAMLTree.new({}, dumper)
   viz << object
   dumper.doc.to_xml
 end

 attr_reader :doc

 def initialize
  @doc       = Nokogiri::XML::Document.new
  @doc.root = @doc.create_element 'root'
  @tags      = []
  @stack = [@doc.root]
 end

 def start_mapping(anchor, tag, implicit, style)
  tag = @doc.create_element('table')
  @stack.last << tag
  @stack     << tag
 end

 def end_mapping
  @stack.pop
 end

 def scalar(value, anchor, tag, *args)
  @stack.last << @doc.create_element('tr').tap do |tag|
    tag << @doc.create_element('td', value)
  end
 end
end
YAML & JSON &
         XML

Psych.dump    Foo.new
Psych.to_json Foo.new
XMLDumper.dump Foo.new
class HTMLDumper < XMLDumper
 def initialize
   @doc      =
Nokogiri::HTML::Document.new
   @doc.root = @doc.create_element('html')
   @doc.root <<
@doc.create_element('body')
   @tags     = []
   @stack = [@doc.root.children.first]
 end
end
YAML & JSON &
      XML & HTML

Psych.dump    Foo.new
Psych.to_json Foo.new
XMLDumper.dump Foo.new
HTMLDumper.dump Foo.new
module Marshalable
 module ClassMethods
  def _load data
   x = allocate
   x.init_with Marshal.load data
   x
  end
 end

 def self.included klass
  klass.extend ClassMethods
 end

 def _dump o
  coder = {}
  encode_with coder
  Marshal.dump coder
 end
end

class Foo; include Marshalable; end
YAML & JSON &
     XML & HTML &
        Marshal
Psych.dump    Foo.new
Psych.to_json Foo.new
XMLDumper.dump Foo.new
HTMLDumper.dump Foo.new
Marshal.dump Foo.new
5 formats in 2
   methods!
Rails is made up of
 interesting things
Investigate those
     things
Improve those
   things
But most of all,
HAVE FUN!
THE END!
Bonus Round!
Twitter Stream
It's JSON!

512
{"in_reply_to_screen_name":null,...}

419
{"in_reply_to_screen_name":"tenderlove"...}
Still JSON!

---
{"in_reply_to_screen_name":null,...}
...
---
{"in_reply_to_screen_name":"tenderlove"...}
...
Event Output


stream = Psych::JSON::Stream.new $stdout
loop do
  stream << { :hello => "world" }
end
---   {'hello': 'world'}
...
---   {'hello': 'world'}
...
---   {'hello': 'world'}
...
---   {'hello': 'world'}
...
Psych + Rack
class StreamAPI
 def call(env)
   reader, writer = IO.pipe

  Thread.new(writer) do |wr|
   stream = Psych::JSON::Stream.new writer
   loop { stream << { :hello => "world" } }
  end

  [200, {}, reader]
 end
end
class StreamAPI
 def call(env)
   reader, writer = IO.pipe

  Thread.new(writer) do |wr|
   stream = Psych::JSON::Stream.new writer
   loop { stream << { :hello => "world" } }
  end

  [200, {}, reader]
 end
end

More Related Content

What's hot

What's hot (20)

PHP 5.4
PHP 5.4PHP 5.4
PHP 5.4
 
Ruby 2.0
Ruby 2.0Ruby 2.0
Ruby 2.0
 
Perl6 Regexen: Reduce the line noise in your code.
Perl6 Regexen: Reduce the line noise in your code.Perl6 Regexen: Reduce the line noise in your code.
Perl6 Regexen: Reduce the line noise in your code.
 
Perl6 grammars
Perl6 grammarsPerl6 grammars
Perl6 grammars
 
On secure application of PHP wrappers
On secure application  of PHP wrappersOn secure application  of PHP wrappers
On secure application of PHP wrappers
 
Findbin libs
Findbin libsFindbin libs
Findbin libs
 
Metadata-driven Testing
Metadata-driven TestingMetadata-driven Testing
Metadata-driven Testing
 
Hypers and Gathers and Takes! Oh my!
Hypers and Gathers and Takes! Oh my!Hypers and Gathers and Takes! Oh my!
Hypers and Gathers and Takes! Oh my!
 
My shell
My shellMy shell
My shell
 
Module 03 Programming on Linux
Module 03 Programming on LinuxModule 03 Programming on Linux
Module 03 Programming on Linux
 
PHP Performance SfLive 2010
PHP Performance SfLive 2010PHP Performance SfLive 2010
PHP Performance SfLive 2010
 
News of the Symfony2 World
News of the Symfony2 WorldNews of the Symfony2 World
News of the Symfony2 World
 
[PL] Jak nie zostać "programistą" PHP?
[PL] Jak nie zostać "programistą" PHP?[PL] Jak nie zostać "programistą" PHP?
[PL] Jak nie zostać "programistą" PHP?
 
Working with databases in Perl
Working with databases in PerlWorking with databases in Perl
Working with databases in Perl
 
Perl6 in-production
Perl6 in-productionPerl6 in-production
Perl6 in-production
 
Perforce Object and Record Model
Perforce Object and Record Model  Perforce Object and Record Model
Perforce Object and Record Model
 
Neatly Hashing a Tree: FP tree-fold in Perl5 & Perl6
Neatly Hashing a Tree: FP tree-fold in Perl5 & Perl6Neatly Hashing a Tree: FP tree-fold in Perl5 & Perl6
Neatly Hashing a Tree: FP tree-fold in Perl5 & Perl6
 
Barely Legal Xxx Perl Presentation
Barely Legal Xxx Perl PresentationBarely Legal Xxx Perl Presentation
Barely Legal Xxx Perl Presentation
 
Percona toolkit
Percona toolkitPercona toolkit
Percona toolkit
 
Symfony 2.0 on PHP 5.3
Symfony 2.0 on PHP 5.3Symfony 2.0 on PHP 5.3
Symfony 2.0 on PHP 5.3
 

Similar to Ruby on Rails: Tasty Burgers

PHP and Rich Internet Applications
PHP and Rich Internet ApplicationsPHP and Rich Internet Applications
PHP and Rich Internet Applicationselliando dias
 
PHP Workshop Notes
PHP Workshop NotesPHP Workshop Notes
PHP Workshop NotesPamela Fox
 
Operation Oriented Web Applications / Yokohama pm7
Operation Oriented Web Applications / Yokohama pm7Operation Oriented Web Applications / Yokohama pm7
Operation Oriented Web Applications / Yokohama pm7Masahiro Nagano
 
SQLite Techniques
SQLite TechniquesSQLite Techniques
SQLite Techniquesjoaopmaia
 
groovy databases
groovy databasesgroovy databases
groovy databasesPaul King
 
Talkaboutlithium
TalkaboutlithiumTalkaboutlithium
Talkaboutlithiumnoppoman722
 
PHP and Rich Internet Applications
PHP and Rich Internet ApplicationsPHP and Rich Internet Applications
PHP and Rich Internet Applicationselliando dias
 
Attributes Unwrapped: Lessons under the surface of active record
Attributes Unwrapped: Lessons under the surface of active recordAttributes Unwrapped: Lessons under the surface of active record
Attributes Unwrapped: Lessons under the surface of active record.toster
 
PHP record- with all programs and output
PHP record- with all programs and outputPHP record- with all programs and output
PHP record- with all programs and outputKavithaK23
 
Debugging: Rules And Tools - PHPTek 11 Version
Debugging: Rules And Tools - PHPTek 11 VersionDebugging: Rules And Tools - PHPTek 11 Version
Debugging: Rules And Tools - PHPTek 11 VersionIan Barber
 
Python postgre sql a wonderful wedding
Python postgre sql   a wonderful weddingPython postgre sql   a wonderful wedding
Python postgre sql a wonderful weddingStéphane Wirtel
 
I Phone On Rails
I Phone On RailsI Phone On Rails
I Phone On RailsJohn Wilker
 
Great Developers Steal
Great Developers StealGreat Developers Steal
Great Developers StealBen Scofield
 
Building and Distributing PostgreSQL Extensions Without Learning C
Building and Distributing PostgreSQL Extensions Without Learning CBuilding and Distributing PostgreSQL Extensions Without Learning C
Building and Distributing PostgreSQL Extensions Without Learning CDavid Wheeler
 
Intro to php
Intro to phpIntro to php
Intro to phpSp Singh
 

Similar to Ruby on Rails: Tasty Burgers (20)

PHP and Rich Internet Applications
PHP and Rich Internet ApplicationsPHP and Rich Internet Applications
PHP and Rich Internet Applications
 
SQLite Techniques
SQLite TechniquesSQLite Techniques
SQLite Techniques
 
PHP Workshop Notes
PHP Workshop NotesPHP Workshop Notes
PHP Workshop Notes
 
Operation Oriented Web Applications / Yokohama pm7
Operation Oriented Web Applications / Yokohama pm7Operation Oriented Web Applications / Yokohama pm7
Operation Oriented Web Applications / Yokohama pm7
 
DataMapper
DataMapperDataMapper
DataMapper
 
SQLite Techniques
SQLite TechniquesSQLite Techniques
SQLite Techniques
 
Hidden Gems of Ruby 1.9
Hidden Gems of Ruby 1.9Hidden Gems of Ruby 1.9
Hidden Gems of Ruby 1.9
 
groovy databases
groovy databasesgroovy databases
groovy databases
 
Quebec pdo
Quebec pdoQuebec pdo
Quebec pdo
 
Talkaboutlithium
TalkaboutlithiumTalkaboutlithium
Talkaboutlithium
 
PHP and Rich Internet Applications
PHP and Rich Internet ApplicationsPHP and Rich Internet Applications
PHP and Rich Internet Applications
 
Attributes Unwrapped: Lessons under the surface of active record
Attributes Unwrapped: Lessons under the surface of active recordAttributes Unwrapped: Lessons under the surface of active record
Attributes Unwrapped: Lessons under the surface of active record
 
Quebec pdo
Quebec pdoQuebec pdo
Quebec pdo
 
PHP record- with all programs and output
PHP record- with all programs and outputPHP record- with all programs and output
PHP record- with all programs and output
 
Debugging: Rules And Tools - PHPTek 11 Version
Debugging: Rules And Tools - PHPTek 11 VersionDebugging: Rules And Tools - PHPTek 11 Version
Debugging: Rules And Tools - PHPTek 11 Version
 
Python postgre sql a wonderful wedding
Python postgre sql   a wonderful weddingPython postgre sql   a wonderful wedding
Python postgre sql a wonderful wedding
 
I Phone On Rails
I Phone On RailsI Phone On Rails
I Phone On Rails
 
Great Developers Steal
Great Developers StealGreat Developers Steal
Great Developers Steal
 
Building and Distributing PostgreSQL Extensions Without Learning C
Building and Distributing PostgreSQL Extensions Without Learning CBuilding and Distributing PostgreSQL Extensions Without Learning C
Building and Distributing PostgreSQL Extensions Without Learning C
 
Intro to php
Intro to phpIntro to php
Intro to php
 

More from Aaron Patterson

More from Aaron Patterson (7)

RubyConf Argentina 2011
RubyConf Argentina 2011RubyConf Argentina 2011
RubyConf Argentina 2011
 
Nordic Ruby 2011
Nordic Ruby 2011Nordic Ruby 2011
Nordic Ruby 2011
 
RailsConf 2011 Keynote
RailsConf 2011 KeynoteRailsConf 2011 Keynote
RailsConf 2011 Keynote
 
Behind the Curtain
Behind the CurtainBehind the Curtain
Behind the Curtain
 
ZOMG WHY IS THIS CODE SO SLOW
ZOMG WHY IS THIS CODE SO SLOWZOMG WHY IS THIS CODE SO SLOW
ZOMG WHY IS THIS CODE SO SLOW
 
RubyConf Brazil 2010
RubyConf Brazil 2010RubyConf Brazil 2010
RubyConf Brazil 2010
 
Worst. Ideas. Ever.
Worst. Ideas. Ever.Worst. Ideas. Ever.
Worst. Ideas. Ever.
 

Recently uploaded

Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteDianaGray10
 
Moving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfMoving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfLoriGlavin3
 
unit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxunit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxBkGupta21
 
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESSALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESmohitsingh558521
 
What is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfWhat is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfMounikaPolabathina
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLScyllaDB
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsPixlogix Infotech
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024Stephanie Beckett
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfAddepto
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii SoldatenkoFwdays
 
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfHyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfPrecisely
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr BaganFwdays
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Commit University
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningLars Bell
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxLoriGlavin3
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .Alan Dix
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsRizwan Syed
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek SchlawackFwdays
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersRaghuram Pandurangan
 

Recently uploaded (20)

Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test Suite
 
Moving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfMoving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdf
 
unit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxunit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptx
 
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESSALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
 
What is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfWhat is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdf
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQL
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and Cons
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdf
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko
 
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfHyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine Tuning
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL Certs
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information Developers
 

Ruby on Rails: Tasty Burgers

Editor's Notes

  1. Connection Pool works as a type of factory, creating connections
  2. Connection Pool works as a type of factory, creating connections
  3. Connection Pool works as a type of factory, creating connections
  4. Connection Pool works as a type of factory, creating connections
  5. Connection Pool works as a type of factory, creating connections
  6. Connection Pool works as a type of factory, creating connections
  7. Connection Pool works as a type of factory, creating connections
  8. Connection Pool works as a type of factory, creating connections
  9. Connection Pool works as a type of factory, creating connections
  10. Connection Pool works as a type of factory, creating connections
  11. Connection Pool works as a type of factory, creating connections