SlideShare a Scribd company logo
Having Fun Programming!
Have Fun
Programming
Programming for
      Fun!
@tenderlove
Having Fun Programming!
Having Fun Programming!
Having Fun Programming!
...
Aaron Patterson
AT&T, AT&T logo and all AT&T related marks are trademarks of AT&T Intellectual Property and/or AT&T affiliated companies.
First
Having Fun Programming!
Ujihisa!
Q: How can I
                                                             enjoy
                                                        programming?




http://www.flickr.com/photos/recompile_net/3733132232/
A: Use Vim!




http://www.flickr.com/photos/recompile_net/3732334373/
•
•
•
•
Having Fun Programming!
Having Fun Programming!
Having Fun Programming!
Having Fun Programming!
Having Fun Programming!
Ruby
Having Fun Programming!
Having Fun Programming!
Having Fun Programming!
Having Fun Programming!
class
end
6.times {
            .new
}
Having Fun Programming!
Thread.new do
        .    ()
end
Thread.new do
      .    ()
end
(Thread.list -[Thread.main]).each
{ |x|
  x.join
}
Having Fun Programming!
• Ruby
•C
• Java
• Lisp
• PHP?
Having Fun Programming!
Having Fun Programming!
We Speak

•
•
•
•
.count


.count
;_;
";_;".encode(   ) # => ":'("
Having Fun Programming!
Having Fun Programming!
Having Fun Programming!
Having Fun Programming!
Having Fun Programming!
!
Having Fun Programming!
Having Fun Programming!
Having Fun Programming!
Having Fun Programming!
Having Fun Programming!
Having Fun Programming!
/
Having Fun Programming!
Having Fun Programming!
Having Fun Programming!
Having Fun Programming!
Ruby Brigades
Seattle.rb
Hack Night
Having Fun Programming!
Having Fun Programming!
Having Fun Programming!
Having Fun Programming!
!!!!
!
!
Having Fun Programming!
Hallway Track
Having Fun Programming!
Having Fun Programming!
Having Fun Programming!
•
•
•
•
•
• Rails 3
•
• XML
• YAML
0 bugs in Ruby 1.9
50% used Ruby 1.9
Having Fun Programming!
Having Fun Programming!
YAML
Psych   Syck
Syck

• Ruby 1.8     1.9

• YAML 1.0 (         ) parser   emitter

•
Psych

• Ruby >= 1.9.2
• libyaml
• YAML 1.1 parser   emitter

•
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')
YAML
require 'psych'

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


---
foo: bar
YAML Map


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


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

Psych.to_json { :foo => 'bar' }
Psych
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">
Independent
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
Having Fun Programming!
Having Fun Programming!
Having Fun Programming!
SQLite3-Ruby
SQLite3-Ruby

• SQLite3
• Jamis Buck
• SWIG
Having Fun Programming!
require 'sqlite3'

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


require 'sqlite3'

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


require 'sqlite3'

connection =
  SQLite3::Database.new(':memory:')
connection.execute('CREATE TABLE foo(id INTEGER)')


connection.execute('INSERT INTO foo (id) VALUES (?)', [10])
stmt = connection.prepare('SELECT * FROM foo WHERE id = ?')

stmt.bind_param(1, 10)

stmt.each do |row|
  p row
end
Having Fun Programming!
Having Fun Programming!
Having Fun Programming!
SQLite3
•   1: API


•   2:


•   3:
: 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
2:
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
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
    File.size(@store.path) - @offset
  end
end
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__
3:
Having Fun Programming!
http://gist.github.com/319224/
SQLite3-Ruby
• Ruby 1.9
• 1000       (   )
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>
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>
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>
(SELECT                         )
                    1.2.5             1.3.0

1000

 100

  10

   1

 0.1

0.01
       500   1000     1500   2000   2500      3000   3500
PHP + Ruby
Phuby!
Ruby.PHP()


Phuby::Runtime.php do |rt|
  rt.eval('$v = strlen("PHP IS AWESOME");')
  puts rt['v'] # => 14
end
Ruby.PHP()

Phuby::Runtime.php do |rt|
  rt.eval('$foo = array();')
  rt.eval('$foo["hello"] = "world";')

  foo = rt['foo'] # => #<Phuby::Array:
0x101f8f848>
  p foo['hello'] # => ‘world’
end
$PHP->Ruby();
class FUN
  def times
    puts "hello"
  end
end

Phuby::Runtime.php do |rt|
  rt['fun'] = FUN.new
  rt.eval('$fun->times();') # => hello
end
PHP
Having Fun Programming!
Having Fun Programming!
Having Fun Programming!
Variable
 Ruby
PHP
rt['foo'] = Foo.new
Ruby          C        PHP

  Weak
              Proxy
Reference               PHP
            (runtime)
  Table




  Ruby
Ruby          C        PHP

  Weak
              Proxy
Reference               PHP
            (runtime)
  Table




  Ruby
PHP   Ruby
$foo->bar();
Ruby          C        PHP

  Weak
              Proxy
Reference               PHP
            (runtime)
  Table




  Ruby
Ruby          C        PHP

  Weak
              Proxy
Reference               PHP
            (runtime)
  Table




  Ruby
Ruby   PHP
rt['foo'].bar()
Ruby      C        PHP


         Proxy
Ruby               PHP
       (runtime)
Ruby      C        PHP


         Proxy
Ruby               PHP
       (runtime)




        Proxy
       (object)
Phuby
PHP + WEBrick
      =
    Blog
Having Fun Programming!
#!/usr/bin/env ruby

require 'rubygems'
require 'phuby'
require 'rack'

##
# Rack::Phrack is a Rack handler that will evaulate and serve PHP files.

class Rack::Phrack < Rack::File
  class Events < Struct.new(:code, :headers, :body)
    def write string; body << string; end
    def send_headers response_code;   end

    def header value, op
      k, v = value.split(': ', 2)
      self.code = 302 if k == 'Location'
      headers[k] = [headers[k], Rack::Utils.unescape(v)].compact.join "n"
    end
  end

  def call   env
    events   = Events.new 200, {}, ''
    file     = File.join @root, env['PATH_INFO']
    file     = File.join file, "index.php" if File.directory?(file)

    return super unless file =~ /php$/

    Dir.chdir(File.dirname(file)) do
      Phuby::Runtime.php do |rt|
        rt.eval "date_default_timezone_set('America/Los_Angeles');" # *shrug*

        { Rack::Utils.parse_query(env['QUERY_STRING'])     => "_GET",
          Rack::Utils.parse_query(env['rack.input'].read) => "_POST",
          Rack::Utils.parse_query(env['HTTP_COOKIE'], ';') => "_COOKIE",
        }.each do |from, to|
          from.each { |k,v| rt[to][k] = v }
        end

        env.each { |k,v| rt['_SERVER'][k] = v || '' unless k =~ /^rack/ }
        rt["_SERVER"]['REQUEST_URI'] = env['PATH_INFO']

        rt.with_events(events) { open(file) { |f| rt.eval f } } # RUN!
      end
    end
    events.to_a
  end
end

Rack::Handler::WEBrick.run(Rack::Phrack.new(ARGV[0] || Dir.pwd), :Port => 10101)
Client



  Phrack



PHPRuntime
Client



  Phrack



PHPRuntime
Having Fun Programming!
Having Fun Programming!
Having Fun Programming!
Having Fun Programming!
Having Fun Programming!
Having Fun Programming!
Special Thanks!
aka @masuidrive
zenspider
Special Request
One Click Installer




    Luis Lavena
Having Fun Programming!
Having Fun Programming!

More Related Content

ZIP
Ruby on Rails: Tasty Burgers
KEY
Getting started with Pod::Weaver
PDF
What's New in PHP 5.5
PDF
The Browser Environment - A Systems Programmer's Perspective
PDF
The Browser Environment - A Systems Programmer's Perspective [sinatra edition]
PDF
Ruby 2.0
PDF
Perforce Object and Record Model
ODP
Whatsnew in-perl
Ruby on Rails: Tasty Burgers
Getting started with Pod::Weaver
What's New in PHP 5.5
The Browser Environment - A Systems Programmer's Perspective
The Browser Environment - A Systems Programmer's Perspective [sinatra edition]
Ruby 2.0
Perforce Object and Record Model
Whatsnew in-perl

What's hot (17)

PDF
Vim Script Programming
PDF
Go for the paranoid network programmer, 3rd edition
PDF
Functional Pe(a)rls - the Purely Functional Datastructures edition
PDF
extending-php
PDF
PHP 7 – What changed internally?
PDF
PHP 7 – What changed internally? (Forum PHP 2015)
PDF
Introdução ao Perl 6
PDF
Descobrindo a linguagem Perl
KEY
Hidden treasures of Ruby
ODP
PHP5.5 is Here
PDF
Functional pe(a)rls: Huey's zipper
KEY
An introduction to Ruby
ODP
Programming Under Linux In Python
PDF
Perl 6 by example
PDF
Is Haskell an acceptable Perl?
PDF
An (Inaccurate) Introduction to Python
PPT
Functional Pe(a)rls version 2
Vim Script Programming
Go for the paranoid network programmer, 3rd edition
Functional Pe(a)rls - the Purely Functional Datastructures edition
extending-php
PHP 7 – What changed internally?
PHP 7 – What changed internally? (Forum PHP 2015)
Introdução ao Perl 6
Descobrindo a linguagem Perl
Hidden treasures of Ruby
PHP5.5 is Here
Functional pe(a)rls: Huey's zipper
An introduction to Ruby
Programming Under Linux In Python
Perl 6 by example
Is Haskell an acceptable Perl?
An (Inaccurate) Introduction to Python
Functional Pe(a)rls version 2
Ad

Similar to Having Fun Programming! (20)

PDF
Attributes Unwrapped: Lessons under the surface of active record
PPTX
PHP in 2018 - Q4 - AFUP Limoges
PDF
Hidden Gems of Ruby 1.9
PDF
Refactoring to Macros with Clojure
PDF
Great Developers Steal
PPTX
ES6 is Nigh
PPT
PHP Workshop Notes
PDF
Ruby - Uma Introdução
PDF
DataMapper
KEY
Operation Oriented Web Applications / Yokohama pm7
PPTX
Building a friendly .NET SDK to connect to Space
PDF
関西PHP勉強会 php5.4つまみぐい
PDF
비윈도우즈 환경의 기술 서적 번역 도구 경험 공유
KEY
Desarrollando aplicaciones web en minutos
PDF
Debugging: Rules & Tools
PDF
Node Boot Camp
PPTX
Introducing PHP Latest Updates
PPT
Fantom and Tales
PPTX
GE8151 Problem Solving and Python Programming
PDF
TYPO3 Extension development using new Extbase framework
Attributes Unwrapped: Lessons under the surface of active record
PHP in 2018 - Q4 - AFUP Limoges
Hidden Gems of Ruby 1.9
Refactoring to Macros with Clojure
Great Developers Steal
ES6 is Nigh
PHP Workshop Notes
Ruby - Uma Introdução
DataMapper
Operation Oriented Web Applications / Yokohama pm7
Building a friendly .NET SDK to connect to Space
関西PHP勉強会 php5.4つまみぐい
비윈도우즈 환경의 기술 서적 번역 도구 경험 공유
Desarrollando aplicaciones web en minutos
Debugging: Rules & Tools
Node Boot Camp
Introducing PHP Latest Updates
Fantom and Tales
GE8151 Problem Solving and Python Programming
TYPO3 Extension development using new Extbase framework
Ad

More from Aaron Patterson (7)

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

Recently uploaded (20)

PDF
Review of recent advances in non-invasive hemoglobin estimation
PDF
solutions_manual_-_materials___processing_in_manufacturing__demargo_.pdf
PDF
Advanced Soft Computing BINUS July 2025.pdf
PPT
Teaching material agriculture food technology
PDF
Network Security Unit 5.pdf for BCA BBA.
PDF
NewMind AI Monthly Chronicles - July 2025
PPTX
Big Data Technologies - Introduction.pptx
PPTX
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
PDF
GDG Cloud Iasi [PUBLIC] Florian Blaga - Unveiling the Evolution of Cybersecur...
PDF
Reach Out and Touch Someone: Haptics and Empathic Computing
PDF
KodekX | Application Modernization Development
PDF
cuic standard and advanced reporting.pdf
PDF
Advanced IT Governance
PDF
Unlocking AI with Model Context Protocol (MCP)
PDF
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
PDF
Modernizing your data center with Dell and AMD
PPTX
breach-and-attack-simulation-cybersecurity-india-chennai-defenderrabbit-2025....
DOCX
The AUB Centre for AI in Media Proposal.docx
PDF
Advanced methodologies resolving dimensionality complications for autism neur...
PDF
NewMind AI Weekly Chronicles - August'25 Week I
Review of recent advances in non-invasive hemoglobin estimation
solutions_manual_-_materials___processing_in_manufacturing__demargo_.pdf
Advanced Soft Computing BINUS July 2025.pdf
Teaching material agriculture food technology
Network Security Unit 5.pdf for BCA BBA.
NewMind AI Monthly Chronicles - July 2025
Big Data Technologies - Introduction.pptx
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
GDG Cloud Iasi [PUBLIC] Florian Blaga - Unveiling the Evolution of Cybersecur...
Reach Out and Touch Someone: Haptics and Empathic Computing
KodekX | Application Modernization Development
cuic standard and advanced reporting.pdf
Advanced IT Governance
Unlocking AI with Model Context Protocol (MCP)
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
Modernizing your data center with Dell and AMD
breach-and-attack-simulation-cybersecurity-india-chennai-defenderrabbit-2025....
The AUB Centre for AI in Media Proposal.docx
Advanced methodologies resolving dimensionality complications for autism neur...
NewMind AI Weekly Chronicles - August'25 Week I

Having Fun Programming!

  • 8. ...
  • 10. AT&T, AT&T logo and all AT&T related marks are trademarks of AT&T Intellectual Property and/or AT&T affiliated companies.
  • 11. First
  • 14. Q: How can I enjoy programming? http://www.flickr.com/photos/recompile_net/3733132232/
  • 22. Ruby
  • 29. Thread.new do . () end Thread.new do . () end (Thread.list -[Thread.main]).each { |x| x.join }
  • 31. • Ruby •C • Java • Lisp • PHP?
  • 36. ;_; ";_;".encode( ) # => ":'("
  • 42. !
  • 49. /
  • 61. !!!!
  • 62. !
  • 63. !
  • 70. • Rails 3 • • XML • YAML
  • 71. 0 bugs in Ruby 1.9
  • 75. YAML Psych Syck
  • 76. Syck • Ruby 1.8 1.9 • YAML 1.0 ( ) parser emitter •
  • 77. Psych • Ruby >= 1.9.2 • libyaml • YAML 1.1 parser emitter •
  • 78. YAML
  • 79. Ruby 1.8 / 1.9 require 'yaml' YAML.load_file('some_file.yml') YAML.load('--- hello world!')
  • 80. Ruby 1.9.2 / Psych require 'psych' Psych.load_file('some_file.yml') Psych.load('--- hello world!')
  • 81. 1.9.2 Opt-in require 'yaml' YAML::ENGINE.yamler = 'psych' YAML.load('--- this is psych')
  • 82. YAML
  • 83. require 'psych' Psych.dump { :foo => 'bar' } { :hello => 'world' }.to_yaml
  • 84. JSON
  • 89. Psych
  • 91. class Foo def initialize @greeting = 'world' end def encode_with(coder) coder['hello'] = @greeting end def init_with(coder) @greeting = coder['hello'] end end
  • 94. Independent class Foo def initialize @greeting = 'world' end def encode_with(coder) coder['hello'] = @greeting end def init_with(coder) @greeting = coder['hello'] end end
  • 95. YAML JSON Psych.dump Foo.new Psych.to_json Foo.new
  • 96. 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
  • 97. YAML, JSON XML Psych.dump Foo.new Psych.to_json Foo.new XMLDumper.dump Foo.new
  • 98. 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
  • 99. YAML, JSON, XML HTML Psych.dump Foo.new Psych.to_json Foo.new XMLDumper.dump Foo.new HTMLDumper.dump Foo.new
  • 100. 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
  • 101. 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
  • 108. require 'sqlite3' connection = SQLite3::Database.new('file.sqlite3')
  • 109. Pro Tip require 'sqlite3' connection = SQLite3::Database.new(':memory:')
  • 110. Pro Tip require 'sqlite3' connection = SQLite3::Database.new(':memory:')
  • 111. connection.execute('CREATE TABLE foo(id INTEGER)') connection.execute('INSERT INTO foo (id) VALUES (?)', [10])
  • 112. stmt = connection.prepare('SELECT * FROM foo WHERE id = ?') stmt.bind_param(1, 10) stmt.each do |row| p row end
  • 117. 1: API • 2: • 3:
  • 118. : 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. */ };
  • 120. 2:
  • 121. 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; }
  • 122. class VFS < SQLite3::VFS def open(name, flags) OurFile.new(name, flags) end end class OurFile def read(...); ... end def write(...); ... end end
  • 125. 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 File.size(@store.path) - @offset end end
  • 126. 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__
  • 127. 3:
  • 131. • Ruby 1.9 • 1000 ( )
  • 132. 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>
  • 133. 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>
  • 134. 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>
  • 135. (SELECT ) 1.2.5 1.3.0 1000 100 10 1 0.1 0.01 500 1000 1500 2000 2500 3000 3500
  • 137. Phuby!
  • 138. Ruby.PHP() Phuby::Runtime.php do |rt| rt.eval('$v = strlen("PHP IS AWESOME");') puts rt['v'] # => 14 end
  • 139. Ruby.PHP() Phuby::Runtime.php do |rt| rt.eval('$foo = array();') rt.eval('$foo["hello"] = "world";') foo = rt['foo'] # => #<Phuby::Array: 0x101f8f848> p foo['hello'] # => ‘world’ end
  • 140. $PHP->Ruby(); class FUN def times puts "hello" end end Phuby::Runtime.php do |rt| rt['fun'] = FUN.new rt.eval('$fun->times();') # => hello end
  • 141. PHP
  • 147. Ruby C PHP Weak Proxy Reference PHP (runtime) Table Ruby
  • 148. Ruby C PHP Weak Proxy Reference PHP (runtime) Table Ruby
  • 149. PHP Ruby
  • 151. Ruby C PHP Weak Proxy Reference PHP (runtime) Table Ruby
  • 152. Ruby C PHP Weak Proxy Reference PHP (runtime) Table Ruby
  • 153. Ruby PHP
  • 155. Ruby C PHP Proxy Ruby PHP (runtime)
  • 156. Ruby C PHP Proxy Ruby PHP (runtime) Proxy (object)
  • 157. Phuby
  • 158. PHP + WEBrick = Blog
  • 160. #!/usr/bin/env ruby require 'rubygems' require 'phuby' require 'rack' ## # Rack::Phrack is a Rack handler that will evaulate and serve PHP files. class Rack::Phrack < Rack::File class Events < Struct.new(:code, :headers, :body) def write string; body << string; end def send_headers response_code; end def header value, op k, v = value.split(': ', 2) self.code = 302 if k == 'Location' headers[k] = [headers[k], Rack::Utils.unescape(v)].compact.join "n" end end def call env events = Events.new 200, {}, '' file = File.join @root, env['PATH_INFO'] file = File.join file, "index.php" if File.directory?(file) return super unless file =~ /php$/ Dir.chdir(File.dirname(file)) do Phuby::Runtime.php do |rt| rt.eval "date_default_timezone_set('America/Los_Angeles');" # *shrug* { Rack::Utils.parse_query(env['QUERY_STRING']) => "_GET", Rack::Utils.parse_query(env['rack.input'].read) => "_POST", Rack::Utils.parse_query(env['HTTP_COOKIE'], ';') => "_COOKIE", }.each do |from, to| from.each { |k,v| rt[to][k] = v } end env.each { |k,v| rt['_SERVER'][k] = v || '' unless k =~ /^rack/ } rt["_SERVER"]['REQUEST_URI'] = env['PATH_INFO'] rt.with_events(events) { open(file) { |f| rt.eval f } } # RUN! end end events.to_a end end Rack::Handler::WEBrick.run(Rack::Phrack.new(ARGV[0] || Dir.pwd), :Port => 10101)
  • 173. One Click Installer Luis Lavena