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

Emixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentEmixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentPim van der Noll
 
Scale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL RouterScale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL RouterMydbops
 
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...AliaaTarek5
 
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...Wes McKinney
 
Manual 508 Accessibility Compliance Audit
Manual 508 Accessibility Compliance AuditManual 508 Accessibility Compliance Audit
Manual 508 Accessibility Compliance AuditSkynet Technologies
 
UiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPathCommunity
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxLoriGlavin3
 
Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Hiroshi SHIBATA
 
Potential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and InsightsPotential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and InsightsRavi Sanghani
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
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
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsSergiu Bodiu
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxLoriGlavin3
 
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...panagenda
 
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
 
A Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersA Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersNicole Novielli
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.Curtis Poe
 
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Mark Goldstein
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality AssuranceInflectra
 

Recently uploaded (20)

Emixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentEmixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native development
 
Scale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL RouterScale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL Router
 
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
 
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
 
Manual 508 Accessibility Compliance Audit
Manual 508 Accessibility Compliance AuditManual 508 Accessibility Compliance Audit
Manual 508 Accessibility Compliance Audit
 
UiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to Hero
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
 
Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024
 
Potential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and InsightsPotential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and Insights
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
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
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platforms
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
 
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
 
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
 
A Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersA Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software Developers
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.
 
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
 

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