93. • Step 1: Read the API
• Step 2: Write your code
• Step 3: Annoy your friends (or profit)
94. 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. */
};
101. 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
102. 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__
117. Template Registration
class Something::ERB < AV::Template::Handler
def render(template, *args)
...
body
end
end
ActionView::Template.register_template_handler(
:erb, Something::ERB
)
161. class MyRack
def call env
[
200,
{'X-RailsConf' => 'yay'},
"hello world!"
]
end
end
162. 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
163. 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
169. class MyRack
def call env
[
200,
{'X-RailsConf' => 'yay'},
File.open(__FILE__, 'rb')
]
end
end
170. 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
218. class Foo
def initialize
@greeting = 'world'
end
def encode_with(coder)
coder['hello'] = @greeting
end
def init_with(coder)
@greeting = coder['hello']
end
end
221. 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
223. 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
225. 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
226. YAML & JSON &
XML & HTML
Psych.dump Foo.new
Psych.to_json Foo.new
XMLDumper.dump Foo.new
HTMLDumper.dump Foo.new
227. 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
228. 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