hidden gems of ruby 1.9

187
HELLO!!!

Upload: aaron-patterson

Post on 11-May-2015

8.779 views

Category:

Documents


6 download

TRANSCRIPT

Page 1: Hidden Gems of Ruby 1.9

HELLO!!!

Page 2: Hidden Gems of Ruby 1.9

ZOMG HAPPY SATURDAY!

Page 3: Hidden Gems of Ruby 1.9

PEW PEW PEW~!!!

Page 4: Hidden Gems of Ruby 1.9

Aaron Patterson

Page 5: Hidden Gems of Ruby 1.9

@tenderlove

Page 6: Hidden Gems of Ruby 1.9

google 'tenderlove'Might be NSFW

Page 7: Hidden Gems of Ruby 1.9

AT&T, AT&T logo and all AT&T related marks are trademarks of AT&T Intellectual Property and/or AT&T affiliated companies.

Page 8: Hidden Gems of Ruby 1.9

Enterprise Developer

http://github.com/tenderlove/enterprise

Page 9: Hidden Gems of Ruby 1.9

ruby core committer

Page 10: Hidden Gems of Ruby 1.9

rails corecommitter

Page 11: Hidden Gems of Ruby 1.9

railscommitter

Page 12: Hidden Gems of Ruby 1.9

My Failures

Page 13: Hidden Gems of Ruby 1.9

rails corecommitter

Page 14: Hidden Gems of Ruby 1.9

railscommitter

Page 15: Hidden Gems of Ruby 1.9

Presenting Last

Page 16: Hidden Gems of Ruby 1.9

I like Ryan Davis

Page 17: Hidden Gems of Ruby 1.9

My Slides Suck(Sorry Shane)

Page 18: Hidden Gems of Ruby 1.9

minitest

Page 19: Hidden Gems of Ruby 1.9

RFC 2119common.rspec

Page 20: Hidden Gems of Ruby 1.9

No Parens on Method Definitions

Page 21: Hidden Gems of Ruby 1.9

def foo bar, baz ...end

Page 22: Hidden Gems of Ruby 1.9

Ruby + JavaScript

Page 23: Hidden Gems of Ruby 1.9

Ruby + C

Page 24: Hidden Gems of Ruby 1.9

My Failures(as a presenter)

Page 25: Hidden Gems of Ruby 1.9

Fun

Page 26: Hidden Gems of Ruby 1.9

Practical

Page 27: Hidden Gems of Ruby 1.9

I am a nerd

Page 28: Hidden Gems of Ruby 1.9

I like boring things

Page 29: Hidden Gems of Ruby 1.9

2 Presentations

Page 30: Hidden Gems of Ruby 1.9

Practical

Page 31: Hidden Gems of Ruby 1.9

Fun!

Page 32: Hidden Gems of Ruby 1.9

The Fun

Page 33: Hidden Gems of Ruby 1.9

Your Guide to Presentation Popularity!

Page 34: Hidden Gems of Ruby 1.9

Your Guide to Presentation

Notoriety!

Page 35: Hidden Gems of Ruby 1.9
Page 36: Hidden Gems of Ruby 1.9

•Provocative Title

•Risqué Photos

•Ruby Code?

Page 37: Hidden Gems of Ruby 1.9

Provocative Title:

Page 38: Hidden Gems of Ruby 1.9

Use Ruby 1.9 like an Engineer

Page 39: Hidden Gems of Ruby 1.9

Use Ruby 1.9 like a SEXY Engineer

Page 40: Hidden Gems of Ruby 1.9

Risqué Photos

Page 41: Hidden Gems of Ruby 1.9

America's Next Top Model

Page 42: Hidden Gems of Ruby 1.9

America's Next Top Engineer

Page 43: Hidden Gems of Ruby 1.9

Confident

Page 44: Hidden Gems of Ruby 1.9

Elegant

Page 45: Hidden Gems of Ruby 1.9

Sultry

Page 46: Hidden Gems of Ruby 1.9

Sexy

Page 47: Hidden Gems of Ruby 1.9

Thoughtful

Page 48: Hidden Gems of Ruby 1.9

Fierce

Page 49: Hidden Gems of Ruby 1.9

Playful

Page 50: Hidden Gems of Ruby 1.9

Powerful

Page 51: Hidden Gems of Ruby 1.9

Provocative

Page 52: Hidden Gems of Ruby 1.9

Ruby Code?

Page 53: Hidden Gems of Ruby 1.9

protected

def method_missing(method, *args, &block) if Array.method_defined?(method) to_a.send(method, *args, &block) elsif @klass.scopes[method] merge(@klass.send(method, *args, &block)) elsif @klass.respond_to?(method) scoping { @klass.send(method, *args, &block) } elsif arel.respond_to?(method) arel.send(method, *args, &block) elsif match = DynamicFinderMatch.match(method) attributes = match.attribute_names super unless @klass.send(:all_attributes_exists?, attributes)

if match.finder? find_by_attributes(match, attributes, *args) elsif match.instantiator? find_or_instantiator_by_attributes(match, attributes, *args, &block) end else super end end

private

def references_eager_loaded_tables? # always convert table names to downcase as in Oracle quoted table names are in uppercase joined_tables = (tables_in_string(arel.joins(arel)) + [table.name, table.table_alias]).compact.map{ |t| t.downcase }.uniq (tables_in_string(to_sql) - joined_tables).any? end

Page 54: Hidden Gems of Ruby 1.9

TL;DR

Page 55: Hidden Gems of Ruby 1.9

The Practical

Page 56: Hidden Gems of Ruby 1.9

Hidden Gems of Ruby 1.9

Page 57: Hidden Gems of Ruby 1.9

Ruby 1.9 PSA

Page 58: Hidden Gems of Ruby 1.9

minitest

Page 59: Hidden Gems of Ruby 1.9

require 'minitest/autorun'

class FooTest < MiniTest::Unit::TestCase WIN32 = true

def test_foo assert_equal 'foo', 'foo' end

def test_refutation refute_equal 'foo', 'bar' end

def test_skip return skip if WIN32 assert_equal 'fun!', 'fun!' endend

Page 60: Hidden Gems of Ruby 1.9

require 'minitest/autorun'

Page 61: Hidden Gems of Ruby 1.9

Test::Unit::TestCase=>

MiniTest::Unit::TestCase

Page 62: Hidden Gems of Ruby 1.9

class FooTest < MiniTest::Unit::TestCaseend

Page 63: Hidden Gems of Ruby 1.9

assert_not_*=>

refute_*

Page 64: Hidden Gems of Ruby 1.9

def test_refutation refute_equal 'foo', 'bar' end

Page 65: Hidden Gems of Ruby 1.9

skip

Page 66: Hidden Gems of Ruby 1.9

class FooTest < MiniTest::Unit::TestCase WIN32 = true

def test_skip skip if WIN32 assert_equal 'fun!', 'fun!' endend

Page 67: Hidden Gems of Ruby 1.9

Loaded suite footestStarted.S.Finished in 0.000682 seconds.

1) Skipped:test_skip(FooTest) [footest.rb:15]:Skipped, no message given

3 tests, 2 assertions, 0 failures, 0 errors, 1 skips

Page 68: Hidden Gems of Ruby 1.9

randomization

Page 69: Hidden Gems of Ruby 1.9

class FailTest < MiniTest::Unit::TestCase @@foos = %w{ hello }

def test_equality assert_equal @@foos, %w{ hello } end

def test_append @@foos << "world" assert_equal @@foos, %w{ hello world } endend

Page 70: Hidden Gems of Ruby 1.9

Test run options: --seed 31149

Loaded suite failtestStarted..Finished in 0.000604 seconds.

2 tests, 2 assertions, 0 failures, 0 errors, 0 skips

Test run options: --seed 31149

Page 71: Hidden Gems of Ruby 1.9

Test run options: --seed 29650

Loaded suite failtestStarted.FFinished in 0.000637 seconds.

1) Failure:test_equality(FailTest) [failtest.rb:7]:Expected ["hello", "world"], not ["hello"].

2 tests, 2 assertions, 1 failures, 0 errors, 0 skips

Test run options: --seed 29650

Page 72: Hidden Gems of Ruby 1.9

Test run options: --seed 29650

Loaded suite failtestStarted.FFinished in 0.000637 seconds.

1) Failure:test_equality(FailTest) [failtest.rb:7]:Expected ["hello", "world"], not ["hello"].

2 tests, 2 assertions, 1 failures, 0 errors, 0 skips

Test run options: --seed 29650

Page 73: Hidden Gems of Ruby 1.9

--seed 29650

Page 74: Hidden Gems of Ruby 1.9

-v

Page 75: Hidden Gems of Ruby 1.9

ruby failtest.rb --seed 29650 -v

Page 76: Hidden Gems of Ruby 1.9

Test run options: --seed 29650 --verbose

Loaded suite failtestStartedFailTest#test_append: 0.00 s: .FailTest#test_equality: 0.00 s: F

Finished in 0.000735 seconds.

1) Failure:test_equality(FailTest) [failtest.rb:7]:Expected ["hello", "world"], not ["hello"].

2 tests, 2 assertions, 1 failures, 0 errors, 0 skips

Test run options: --seed 29650 --verbose

Page 77: Hidden Gems of Ruby 1.9

Test run options: --seed 29650 --verbose

Loaded suite failtestStartedFailTest#test_append: 0.00 s: .FailTest#test_equality: 0.00 s: F

Finished in 0.000735 seconds.

1) Failure:test_equality(FailTest) [failtest.rb:7]:Expected ["hello", "world"], not ["hello"].

2 tests, 2 assertions, 1 failures, 0 errors, 0 skips

Test run options: --seed 29650 --verbose

Page 78: Hidden Gems of Ruby 1.9

Test Performance

Page 79: Hidden Gems of Ruby 1.9

class FooTest < MiniTest::Unit::TestCase def test_foo assert_equal 'foo', 'foo' end

def test_refutation refute_equal 'foo', 'bar' end

def test_slow sleep 10 endend

Page 80: Hidden Gems of Ruby 1.9

class FooTest < MiniTest::Unit::TestCase def test_foo assert_equal 'foo', 'foo' end

def test_refutation refute_equal 'foo', 'bar' end

def test_slow sleep 10 endend

Page 81: Hidden Gems of Ruby 1.9

Test run options: --seed 33095 --verbose

Loaded suite footestStartedFooTest#test_slow: 10.00 s: .FooTest#test_refutation: 0.00 s: .FooTest#test_foo: 0.00 s: .

Finished in 10.001114 seconds.

3 tests, 2 assertions, 0 failures, 0 errors, 0 skips

Test run options: --seed 33095 --verbose

Page 82: Hidden Gems of Ruby 1.9

Test run options: --seed 33095 --verbose

Loaded suite footestStartedFooTest#test_slow: 10.00 s: .FooTest#test_refutation: 0.00 s: .FooTest#test_foo: 0.00 s: .

Finished in 10.001114 seconds.

3 tests, 2 assertions, 0 failures, 0 errors, 0 skips

Test run options: --seed 33095 --verbose

Page 83: Hidden Gems of Ruby 1.9

With Rake:

Page 84: Hidden Gems of Ruby 1.9

rake test TESTSOPTS='-v'

Page 85: Hidden Gems of Ruby 1.9

rspec

Page 86: Hidden Gems of Ruby 1.9

describe 'Awesome' do describe 'Class' do it 'discovers something AMAZING' do (10 + 10).must_equal 20 end

it 'matches something AMAZING' do "vuvuzela".must_match /vuvu/ end

it 'raises something AMAZING' do lambda { raise }.must_raise(RuntimeError) end endend

Page 87: Hidden Gems of Ruby 1.9

rspec

Page 88: Hidden Gems of Ruby 1.9

minitest/spec

Page 89: Hidden Gems of Ruby 1.9

require 'minitest/spec'require 'minitest/autorun'

Page 90: Hidden Gems of Ruby 1.9

require 'minitest/spec'require 'minitest/autorun'

describe 'Awesome' do describe 'Class' do it 'discovers something AMAZING' do (10 + 10).must_equal 20 end

it 'matches something AMAZING' do "vuvuzela".must_match /vuvu/ end

it 'must raise something' do lambda { raise }.must_raise(RuntimeError) end endend

Page 91: Hidden Gems of Ruby 1.9

ObjectSpace

Page 92: Hidden Gems of Ruby 1.9

ObjectSpace.each_object do |obj| p objend

Page 93: Hidden Gems of Ruby 1.9

require 'objspace'

• count_objects_size

•memsize_of

• count_nodes

• count_tdata_objects

Page 94: Hidden Gems of Ruby 1.9

count_object_size

require 'objspace'

hash = {}ObjectSpace.count_objects_size(hash)p hash # => {:T_CLASS=>291520, :T_MODULE=>42512, :T_STRING=>26133, :T_REGEXP=>11501, :T_ARRAY=>5896, :T_HASH=>1088, :T_FILE=>9056, :T_DATA=>1144348, :TOTAL=>1532054}

Page 95: Hidden Gems of Ruby 1.9

count_object_size

require 'objspace'

hash = {}ObjectSpace.count_objects_size(hash)p hash # => {:T_CLASS=>291520, :T_MODULE=>42512, :T_STRING=>26133, :T_REGEXP=>11501, :T_ARRAY=>5896, :T_HASH=>1088, :T_FILE=>9056, :T_DATA=>1144348, :TOTAL=>1532054}

Page 96: Hidden Gems of Ruby 1.9

memsize_of

require 'objspace'require 'fiddle'

cl = Fiddle::Closure.new(0, [1])p ObjectSpace.memsize_of(cl) # => 232

Page 97: Hidden Gems of Ruby 1.9

memsize_of

require 'objspace'require 'fiddle'

cl = Fiddle::Closure.new(0, [1])p ObjectSpace.memsize_of(cl) # => 232

Page 98: Hidden Gems of Ruby 1.9

Implementation

Page 99: Hidden Gems of Ruby 1.9

struct rb_data_type_struct

struct rb_data_type_struct { const char *wrap_struct_name; struct { void (*dmark)(void*); void (*dfree)(void*); size_t (*dsize)(const void *); void *reserved[2]; /* For future extension. This array *must* be filled with ZERO. */ } function; const rb_data_type_t *parent; void *data; /* This area can be used for any purpose by a programmer who define the type. */};

Page 100: Hidden Gems of Ruby 1.9

struct rb_data_type_struct

struct rb_data_type_struct { const char *wrap_struct_name; struct { void (*dmark)(void*); void (*dfree)(void*); size_t (*dsize)(const void *); void *reserved[2]; /* For future extension. This array *must* be filled with ZERO. */ } function; const rb_data_type_t *parent; void *data; /* This area can be used for any purpose by a programmer who define the type. */};

Page 101: Hidden Gems of Ruby 1.9

static size_t my_memsize(const void *p) { return 10;}

const rb_data_type_t my_data_type = { "my_extension", {NULL, NULL, my_memsize,},};

static VALUE allocate(VALUE klass) { struct something * cif; return TypedData_Make_Struct( klass, something, &my_data_type, cif);}

Page 102: Hidden Gems of Ruby 1.9

count_nodes

require 'objspace'

p ObjectSpace.count_nodes #=> {:NODE_SCOPE=>50, :NODE_BLOCK=>168, :NODE_IF=>27, :NODE_ITER=>7, ... }

Page 103: Hidden Gems of Ruby 1.9

count_nodes

require 'objspace'

p ObjectSpace.count_nodes #=> {:NODE_SCOPE=>50, :NODE_BLOCK=>168, :NODE_IF=>27, :NODE_ITER=>7, ... }

Page 104: Hidden Gems of Ruby 1.9

count_nodes

require 'objspace'

10.times do p ObjectSpace.count_nodes[:NODE_IF] eval 'if true; end'end

Page 105: Hidden Gems of Ruby 1.9

$ ruby objectspace.rb 27282930313233343536$

Page 106: Hidden Gems of Ruby 1.9

count_tdata_objects

require 'objspace'

p ObjectSpace.count_tdata_objects # => {RubyVM::InstructionSequence=>64, false=>13, ... }

Page 107: Hidden Gems of Ruby 1.9

count_tdata_objects

require 'objspace'

p ObjectSpace.count_tdata_objects # => {RubyVM::InstructionSequence=>64, false=>13, ... }

Page 108: Hidden Gems of Ruby 1.9

count_tdata_objects

require 'objspace'require 'fiddle'

10.times do Fiddle::Closure.new(0, [1]) p ObjectSpace.count_tdata_objects[Fiddle::Closure]end

Page 109: Hidden Gems of Ruby 1.9

$ ruby objectspace.rb 12345678910$

Page 110: Hidden Gems of Ruby 1.9

Fiddle

Page 111: Hidden Gems of Ruby 1.9

libffi wrapper

Page 112: Hidden Gems of Ruby 1.9

fiddle + dl

Page 113: Hidden Gems of Ruby 1.9

Fiddle

• Function calls

•Closure allocation

Page 114: Hidden Gems of Ruby 1.9

DL

• dlopen() wrapper

•memory management

Page 115: Hidden Gems of Ruby 1.9

Calling Functions

Page 116: Hidden Gems of Ruby 1.9

•Open dynamic library

• Locate function pointer

•Wrap function pointer

•Call function

Page 117: Hidden Gems of Ruby 1.9

require 'fiddle'

libm = DL.dlopen('libm.dylib')

function = Fiddle::Function.new( libm['sin'], [Fiddle::TYPE_DOUBLE], Fiddle::TYPE_DOUBLE)

puts function.call(90 * Math::PI / 180)

Wrapping "sin"

Page 118: Hidden Gems of Ruby 1.9

require 'fiddle'

libm = DL.dlopen('libm.dylib')

function = Fiddle::Function.new( libm['sin'], [Fiddle::TYPE_DOUBLE], Fiddle::TYPE_DOUBLE)

puts function.call(90 * Math::PI / 180)

Wrapping "sin"

Page 119: Hidden Gems of Ruby 1.9

require 'fiddle'

libm = DL.dlopen('libm.dylib')

function = Fiddle::Function.new( libm['sin'], [Fiddle::TYPE_DOUBLE], Fiddle::TYPE_DOUBLE)

puts function.call(90 * Math::PI / 180)

Wrapping "sin"

Page 120: Hidden Gems of Ruby 1.9

require 'fiddle'

libm = DL.dlopen('libm.dylib')

function = Fiddle::Function.new( libm['sin'], [Fiddle::TYPE_DOUBLE], Fiddle::TYPE_DOUBLE)

puts function.call(90 * Math::PI / 180)

Wrapping "sin"

Page 121: Hidden Gems of Ruby 1.9

require 'fiddle'

libm = DL.dlopen('libm.dylib')

function = Fiddle::Function.new( libm['sin'], [Fiddle::TYPE_DOUBLE], Fiddle::TYPE_DOUBLE)

puts function.call(90 * Math::PI / 180)

Wrapping "sin"

Page 122: Hidden Gems of Ruby 1.9

Creating Closures

Page 123: Hidden Gems of Ruby 1.9

double (func *)(double)

Page 124: Hidden Gems of Ruby 1.9

require 'fiddle'

class MySin < Fiddle::Closure def call number Math.sin(number) endend

function = MySin.new( Fiddle::TYPE_DOUBLE, [Fiddle::TYPE_DOUBLE])

puts function.call(90 * Math::PI / 180)

Page 125: Hidden Gems of Ruby 1.9

require 'fiddle'

class MySin < Fiddle::Closure def call(number) Math.sin(number) endend

function = MySin.new( Fiddle::TYPE_DOUBLE, [Fiddle::TYPE_DOUBLE])

puts function.call(90 * Math::PI / 180)

Page 126: Hidden Gems of Ruby 1.9

require 'fiddle'

class MySin < Fiddle::Closure def call(number) Math.sin(number) endend

function = MySin.new( Fiddle::TYPE_DOUBLE, [Fiddle::TYPE_DOUBLE])

puts function.call(90 * Math::PI / 180)

Page 127: Hidden Gems of Ruby 1.9

require 'fiddle'

class MySin < Fiddle::Closure def call(number) Math.sin(number) endend

function = MySin.new( Fiddle::TYPE_DOUBLE, [Fiddle::TYPE_DOUBLE])

puts function.call(90 * Math::PI / 180)

Page 128: Hidden Gems of Ruby 1.9

Using our Closure

Page 129: Hidden Gems of Ruby 1.9

class MySin < Fiddle::Closure def call number Math.sin(number) endend

function = MySin.new( Fiddle::TYPE_DOUBLE, [Fiddle::TYPE_DOUBLE])

cfunc = Fiddle::Function.new( function, [Fiddle::TYPE_DOUBLE], Fiddle::TYPE_DOUBLE)

puts cfunc.call(90 * Math::PI / 180)

Page 130: Hidden Gems of Ruby 1.9

class MySin < Fiddle::Closure def call number Math.sin(number) endend

function = MySin.new( Fiddle::TYPE_DOUBLE, [Fiddle::TYPE_DOUBLE])

cfunc = Fiddle::Function.new( function, [Fiddle::TYPE_DOUBLE], Fiddle::TYPE_DOUBLE)

puts cfunc.call(90 * Math::PI / 180)

Page 131: Hidden Gems of Ruby 1.9

Fiddle Masquerade

Page 132: Hidden Gems of Ruby 1.9

ruby-ffi codemodule Tidy extend FFI::Library

ffi_lib "libtidy.dylib"

attach_function :tidyFileExists, [:string], :int attach_function :tidyCreate, [], :pointer attach_function :tidyParseString, [:pointer, :string], :int attach_function :tidySaveStdout, [:pointer], :intend

tdoc = Tidy.tidyCreateTidy.tidyParseString tdoc, "<title>Foo</title"Tidy.tidySaveStdout tdoc

Page 133: Hidden Gems of Ruby 1.9

In terms of Fiddle

Page 134: Hidden Gems of Ruby 1.9

module FFI module Library TYPE_MAP = { :string => DL::TYPE_VOIDP, :pointer => DL::TYPE_VOIDP, }

DL.constants.each do |const| next unless const.to_s =~ /^TYPE_/

name = const.to_s.split('_', 2).last.downcase.to_sym TYPE_MAP[name] = DL.const_get(const) end

def ffi_lib(lib) @lib = DL::Handle.new lib end

def attach_function(name, args, ret) func = Fiddle::Function.new( @lib[name.to_s], args.map { |x| TYPE_MAP[x] }, TYPE_MAP[ret] )

define_singleton_method(name) { |*args| func.call(*args) } end endend

Page 135: Hidden Gems of Ruby 1.9

ruby-ffi codemodule Tidy extend FFI::Library

ffi_lib "libtidy.dylib"

attach_function :tidyFileExists, [:string], :int attach_function :tidyCreate, [], :pointer attach_function :tidyParseString, [:pointer, :string], :int attach_function :tidySaveStdout, [:pointer], :intend

tdoc = Tidy.tidyCreateTidy.tidyParseString tdoc, "<title>Foo</title"Tidy.tidySaveStdout tdoc

Page 136: Hidden Gems of Ruby 1.9

Fiddle codemodule Tidy extend FFI::Library

ffi_lib "libtidy.dylib"

attach_function :tidyFileExists, [:string], :int attach_function :tidyCreate, [], :pointer attach_function :tidyParseString, [:pointer, :string], :int attach_function :tidySaveStdout, [:pointer], :intend

tdoc = Tidy.tidyCreateTidy.tidyParseString tdoc, "<title>Foo</title"Tidy.tidySaveStdout tdoc

Page 137: Hidden Gems of Ruby 1.9

Psych

Page 138: Hidden Gems of Ruby 1.9

YAML Parser

• 1.9.2 and up

•Wraps libyaml

•Replaces Syck

•Opt-in

Page 139: Hidden Gems of Ruby 1.9

Opt-in Process

$ irbirb(main):001:0> require 'yaml'=> trueirb(main):002:0> YAML::ENGINE.syck?=> trueirb(main):003:0> YAML::ENGINE.yamler = 'psych'=> "psych"irb(main):004:0> YAML::ENGINE.syck?=> falseirb(main):005:0>

Page 140: Hidden Gems of Ruby 1.9

require 'psych'

Page 141: Hidden Gems of Ruby 1.9

Parsing & Dumping

require 'psych'

Psych.load('--- hello world!') # => 'hello world!'Psych.dump('hello world!') # => '--- hello world!''hello world!'.to_yaml # => '--- hello world!'

Page 142: Hidden Gems of Ruby 1.9

JSON

Psych.load("['hello', 'world!']\n") # => ["hello", "world!"]

Psych.to_json(%w{ hello world! }) # => "['hello', 'world!']\n"

Page 143: Hidden Gems of Ruby 1.9

JSON Disclaimer

Page 144: Hidden Gems of Ruby 1.9

Evented Parsing

Page 145: Hidden Gems of Ruby 1.9

Evented Parsingclass MyHandler < Psych::Handler def start_sequence(*args) puts "open [" end

def end_sequence(*args) puts "close ]" end

def scalar(value, anchor, tag, plain, quoted, style) puts value endend

Page 146: Hidden Gems of Ruby 1.9

Evented Parsing

parser = Psych::Parser.new(MyHandler.new)parser.parse(StringIO.new("['foo', 'bar']"))

Page 147: Hidden Gems of Ruby 1.9

Evented Parsing

$ ruby yml.rb open [foobarclose ]$

Page 148: Hidden Gems of Ruby 1.9

Psych::Parser#parse(io_or_string)

Page 149: Hidden Gems of Ruby 1.9

Evented Emitting

Page 150: Hidden Gems of Ruby 1.9

(the hard way)

Page 151: Hidden Gems of Ruby 1.9

emitter = Psych::Emitter.new($stdout)

emitter.start_stream(Psych::Parser::UTF8)emitter.start_document([], [], false)emitter.start_sequence(nil, nil, false, 1)10.times { emitter.scalar('hello world', nil, nil, false, true, 1)}emitter.end_sequenceemitter.end_document trueemitter.end_stream

Psych::Emitter

Page 152: Hidden Gems of Ruby 1.9

---- 'hello world'- 'hello world'- 'hello world'- 'hello world'- 'hello world'- 'hello world'- 'hello world'- 'hello world'- 'hello world'- 'hello world'

Page 153: Hidden Gems of Ruby 1.9

ReadPsych::Handler

Page 154: Hidden Gems of Ruby 1.9

Streamed Emitting

Page 155: Hidden Gems of Ruby 1.9

(the easy way)

Page 156: Hidden Gems of Ruby 1.9

emitter = Psych::Stream.new($stdout)emitter.startemitter.push %w{ one two }emitter.push %w{ three four }emitter.finish

Psych::Stream

Page 157: Hidden Gems of Ruby 1.9

emitter = Psych::Stream.new($stdout)emitter.startemitter.push %w{ one two }emitter.push %w{ three four }emitter.finish

Psych::Stream

Page 158: Hidden Gems of Ruby 1.9

Psych::Stream

$ ruby yml.rb ---- one- two...---- three- four...

Page 159: Hidden Gems of Ruby 1.9

Problem?

Page 160: Hidden Gems of Ruby 1.9

Streaming JSON

Page 161: Hidden Gems of Ruby 1.9

emitter = Psych::Stream.new($stdout)emitter.startemitter.push %w{ one two }emitter.push %w{ three four }emitter.finish

Psych::Stream

Page 162: Hidden Gems of Ruby 1.9

emitter = Psych::JSON::Stream.new($stdout)emitter.startemitter.push %w{ one two }emitter.push %w{ three four }emitter.finish

Psych::JSON::Stream

Page 163: Hidden Gems of Ruby 1.9

emitter = Psych::JSON::Stream.new($stdout)emitter.startemitter.push %w{ one two }emitter.push %w{ three four }emitter.finish

Psych::JSON::Stream

Page 164: Hidden Gems of Ruby 1.9

--- ['one', 'two']...--- ['three', 'four']...

Psych::JSON::Stream

Page 165: Hidden Gems of Ruby 1.9

Uses?

Page 166: Hidden Gems of Ruby 1.9

More Info

Page 167: Hidden Gems of Ruby 1.9

THE END

Page 168: Hidden Gems of Ruby 1.9
Page 169: Hidden Gems of Ruby 1.9

Questions?

Page 170: Hidden Gems of Ruby 1.9

Coverage

Page 171: Hidden Gems of Ruby 1.9

Methods

•Coverage.start

•Coverage.result

Page 172: Hidden Gems of Ruby 1.9

#### It's my class!class Foo def initialize @thought = 0 10.times { @thought += 1 # thinking } end

def rested? if @thought > 8 false else true end endend

Foo.new.rested?

a.rb

Page 173: Hidden Gems of Ruby 1.9

#### It's my class!class Foo def initialize @thought = 0 10.times { @thought += 1 # thinking } end

def rested? if @thought > 8 false else true end endend

Foo.new.rested?

a.rb

Page 174: Hidden Gems of Ruby 1.9

#### It's my class!class Foo def initialize @thought = 0 10.times { @thought += 1 # thinking } end

def rested? if @thought > 8 false else true end endend

Foo.new.rested?

a.rb

Page 175: Hidden Gems of Ruby 1.9

#### It's my class!class Foo def initialize @thought = 0 10.times { @thought += 1 # thinking } end

def rested? if @thought > 8 false else true end endend

Foo.new.rested?

a.rb

Page 176: Hidden Gems of Ruby 1.9

require 'coverage'

Coverage.startrequire 'a'p Coverage.result

Page 177: Hidden Gems of Ruby 1.9

require 'coverage'

Coverage.startrequire 'a'p Coverage.result

Page 178: Hidden Gems of Ruby 1.9

{"/Users/apatterson/git/code/a.rb"=>[nil, nil, 1, 1, 1, 1, 10, nil, nil, nil, 1, 1, 1, nil, 0, nil, nil, nil, nil, 1]}

Coverage.result

Page 179: Hidden Gems of Ruby 1.9

We've Learned

Page 180: Hidden Gems of Ruby 1.9

We've Learned

• Lines executed

Page 181: Hidden Gems of Ruby 1.9

We've Learned

• Lines executed

• # times a line was executed

Page 182: Hidden Gems of Ruby 1.9

We've Learned

• Lines executed

• # times a line was executed

• Lines that can't be executed

Page 183: Hidden Gems of Ruby 1.9

We can deduce

Page 184: Hidden Gems of Ruby 1.9

We can deduce

•Coverage

Page 185: Hidden Gems of Ruby 1.9

We can deduce

•Coverage

•Hotspots (code heatmap)

Page 186: Hidden Gems of Ruby 1.9

SimpleCovhttp://github.com/colszowka/simplecov