150
The Dark Side of Ruby @gautamrege @joshsoftware

RedDot Ruby Conf 2014 - Dark side of ruby

Embed Size (px)

DESCRIPTION

I love Ruby! But as in any relationship, to love means that you (often) have to accept the “dark side” too! Ruby is human in nature and has a lot of gotchas, tricks, weirdness and sometimes scary features that I plan to highlight. This talk aims to provide the “Ah-ha!” moments when working in Ruby. This talk is for beginners and experts alike - in fact, I tag slides to mark their level and beginners can choose to tune out of the heavy stuff! My talk shall cover the dark side of the following features of Ruby (in no particular order) Keyword wierdness method missing Module inheritance! (huh?) Accessor righteousness Curried Procs for the hungry Base Conversions Cherry picking module methods Oniguruma games Object id weirdness procs, blocks and our friend stabby. ==, ===, eql? and equal? and more… As with most of my talks, humor plays an important role and I shall aim to get everyone high on Ruby with a deep dive!

Citation preview

Page 1: RedDot Ruby Conf 2014 - Dark side of ruby

The Dark Side of Ruby

@gautamrege!@joshsoftware

Page 2: RedDot Ruby Conf 2014 - Dark side of ruby

What’s the talk about?

Page 3: RedDot Ruby Conf 2014 - Dark side of ruby

What’s the talk about?• Ruby is AWESOME but …

Page 4: RedDot Ruby Conf 2014 - Dark side of ruby

What’s the talk about?• Ruby is AWESOME but …

• Nothing scary

Page 5: RedDot Ruby Conf 2014 - Dark side of ruby

What’s the talk about?• Ruby is AWESOME but …

• Nothing scary really

Page 6: RedDot Ruby Conf 2014 - Dark side of ruby

What’s the talk about?• Ruby is AWESOME but …

• Nothing scary

• Weirdness and Gotcha’s

really

Page 7: RedDot Ruby Conf 2014 - Dark side of ruby

What’s the talk about?• Ruby is AWESOME but …

• Nothing scary

• Weirdness and Gotcha’s

Ah-ha! Moments

really

Page 8: RedDot Ruby Conf 2014 - Dark side of ruby

Slides are Tagged

Page 9: RedDot Ruby Conf 2014 - Dark side of ruby

Slides are Tagged

Beginner

Page 10: RedDot Ruby Conf 2014 - Dark side of ruby

Slides are Tagged

Expert

Page 11: RedDot Ruby Conf 2014 - Dark side of ruby

(In)Famous Infinityhttp://www.flickr.com/photos/emdot/482622478/sizes/l/

Page 12: RedDot Ruby Conf 2014 - Dark side of ruby

(In)Famous Infinity

Page 13: RedDot Ruby Conf 2014 - Dark side of ruby

(In)Famous Infinity

Page 14: RedDot Ruby Conf 2014 - Dark side of ruby

(In)Famous Infinity$ irb> 1/0

Page 15: RedDot Ruby Conf 2014 - Dark side of ruby

(In)Famous Infinity$ irb> 1/0=> ZeroDivisionError: divided by 0

Page 16: RedDot Ruby Conf 2014 - Dark side of ruby

(In)Famous Infinity$ irb> 1/0

$ irb> 1.0/0

=> ZeroDivisionError: divided by 0

Page 17: RedDot Ruby Conf 2014 - Dark side of ruby

(In)Famous Infinity$ irb> 1/0

$ irb> 1.0/0

=> ZeroDivisionError: divided by 0

=> Infinity

Page 18: RedDot Ruby Conf 2014 - Dark side of ruby

(In)Famous Infinity$ irb> 1/0

$ irb> 1.0/0

$ irb> Infinity

=> ZeroDivisionError: divided by 0

=> Infinity

Page 19: RedDot Ruby Conf 2014 - Dark side of ruby

(In)Famous Infinity$ irb> 1/0

$ irb> 1.0/0

$ irb> Infinity

=> ZeroDivisionError: divided by 0

=> Infinity

=> NameError: uninitialized constant Infinity

Page 20: RedDot Ruby Conf 2014 - Dark side of ruby

(In)Famous Infinity

Page 21: RedDot Ruby Conf 2014 - Dark side of ruby

(In)Famous Infinity

Page 22: RedDot Ruby Conf 2014 - Dark side of ruby

(In)Famous Infinity#if !defined(INFINITY) || !defined(NAN)!union bytesequence4_or_float {! unsigned char bytesequence[4];! float float_value;!};!#endif!!RUBY_EXTERN const union bytesequence4_or_float rb_infinity;

Page 23: RedDot Ruby Conf 2014 - Dark side of ruby

(In)Famous Infinity#if !defined(INFINITY) || !defined(NAN)!union bytesequence4_or_float {! unsigned char bytesequence[4];! float float_value;!};!#endif!!RUBY_EXTERN const union bytesequence4_or_float rb_infinity;

include/ruby/missing.h

Page 24: RedDot Ruby Conf 2014 - Dark side of ruby

Base Jumping

http://www.flickr.com/photos/shahdi/8035647153/sizes/l/

Page 25: RedDot Ruby Conf 2014 - Dark side of ruby

Base Conversions

Page 26: RedDot Ruby Conf 2014 - Dark side of ruby

Base Conversions

Page 27: RedDot Ruby Conf 2014 - Dark side of ruby

Base Conversions$ irb> 12345.to_s(8)

Page 28: RedDot Ruby Conf 2014 - Dark side of ruby

Base Conversions$ irb> 12345.to_s(8)=> "30071" # => Octal

Page 29: RedDot Ruby Conf 2014 - Dark side of ruby

Base Conversions$ irb> 12345.to_s(8)

$ irb> 12345.to_s(36)

=> "30071" # => Octal

Page 30: RedDot Ruby Conf 2014 - Dark side of ruby

Base Conversions$ irb> 12345.to_s(8)

$ irb> 12345.to_s(36)

=> "30071" # => Octal

=> "9ix" # That is an actual number

Page 31: RedDot Ruby Conf 2014 - Dark side of ruby

Base Conversions$ irb> 12345.to_s(8)

$ irb> 12345.to_s(36)

$ irb> 1234.to_s(64)

=> "30071" # => Octal

=> "9ix" # That is an actual number

Page 32: RedDot Ruby Conf 2014 - Dark side of ruby

Base Conversions$ irb> 12345.to_s(8)

$ irb> 12345.to_s(36)

$ irb> 1234.to_s(64)

=> "30071" # => Octal

=> "9ix" # That is an actual number

=> ArgumentError: invalid radix 64

Page 33: RedDot Ruby Conf 2014 - Dark side of ruby
Page 34: RedDot Ruby Conf 2014 - Dark side of ruby

Hashes and Arrays

Page 35: RedDot Ruby Conf 2014 - Dark side of ruby

Hashes and Arrays

Page 36: RedDot Ruby Conf 2014 - Dark side of ruby

Hashes and Arraysa=[1,2,3,4,5,6]!h=Hash[*a]

Page 37: RedDot Ruby Conf 2014 - Dark side of ruby

Hashes and Arraysa=[1,2,3,4,5,6]!h=Hash[*a]=> {1=>2, 3=>4, 5=>6}

Page 38: RedDot Ruby Conf 2014 - Dark side of ruby

Hashes and Arraysa=[1,2,3,4,5,6]!h=Hash[*a]=> {1=>2, 3=>4, 5=>6}

[1,2,3] * 3

Page 39: RedDot Ruby Conf 2014 - Dark side of ruby

Hashes and Arraysa=[1,2,3,4,5,6]!h=Hash[*a]=> {1=>2, 3=>4, 5=>6}

[1,2,3] * 3=> [1,2,3,1,2,3,1,2,3]

Page 40: RedDot Ruby Conf 2014 - Dark side of ruby

Hashes and Arraysa=[1,2,3,4,5,6]!h=Hash[*a]=> {1=>2, 3=>4, 5=>6}

[1,2,3] * 3=> [1,2,3,1,2,3,1,2,3]

[1,2,3] * "%"

Page 41: RedDot Ruby Conf 2014 - Dark side of ruby

Hashes and Arraysa=[1,2,3,4,5,6]!h=Hash[*a]=> {1=>2, 3=>4, 5=>6}

[1,2,3] * 3=> [1,2,3,1,2,3,1,2,3]

[1,2,3] * "%"=> "1%2%3"

Page 42: RedDot Ruby Conf 2014 - Dark side of ruby

Calling out to Stabby

Page 43: RedDot Ruby Conf 2014 - Dark side of ruby

Calling out to Stabbyblk = ->(f, *m, sl, l) do puts sl end

Page 44: RedDot Ruby Conf 2014 - Dark side of ruby

Calling out to Stabbyblk = ->(f, *m, sl, l) do puts sl end

blk.call(1, 2, 3, 4, 5, 6)

Page 45: RedDot Ruby Conf 2014 - Dark side of ruby

Calling out to Stabbyblk = ->(f, *m, sl, l) do puts sl end

blk.call(1, 2, 3, 4, 5, 6)=> 5

Page 46: RedDot Ruby Conf 2014 - Dark side of ruby

blk.(1, 2, 3, 4, 5, 6)

Calling out to Stabbyblk = ->(f, *m, sl, l) do puts sl end

blk.call(1, 2, 3, 4, 5, 6)=> 5

Page 47: RedDot Ruby Conf 2014 - Dark side of ruby

blk.(1, 2, 3, 4, 5, 6)

Calling out to Stabbyblk = ->(f, *m, sl, l) do puts sl end

blk.call(1, 2, 3, 4, 5, 6)=> 5

Page 48: RedDot Ruby Conf 2014 - Dark side of ruby

blk.(1, 2, 3, 4, 5, 6)=> 5

syntax sugar for call blk[1,2,3,4,5,6]

Calling out to Stabbyblk = ->(f, *m, sl, l) do puts sl end

blk.call(1, 2, 3, 4, 5, 6)=> 5

Page 49: RedDot Ruby Conf 2014 - Dark side of ruby

Syntax

Page 50: RedDot Ruby Conf 2014 - Dark side of ruby

Syntax def foo(a=1, b=1,opts={})

end

Page 51: RedDot Ruby Conf 2014 - Dark side of ruby

Syntax def foo(a: 1, b: 2)

end

Page 52: RedDot Ruby Conf 2014 - Dark side of ruby

Syntax def foo(a: 1, b: 2)

endkeyword arguments

Page 53: RedDot Ruby Conf 2014 - Dark side of ruby

Syntax

def foo(a: 1, b:, c: 2)

end

def foo(a: 1, b: 2)

endkeyword arguments

Page 54: RedDot Ruby Conf 2014 - Dark side of ruby

Syntax

def foo(a: 1, b:, c: 2)

end

def foo(a: 1, b: 2)

endkeyword arguments

Page 55: RedDot Ruby Conf 2014 - Dark side of ruby

Syntax

def foo(a: 1, b:, c: 2)

end

foo(a: 2) => ArgumentError: missing keyword: b

Mandatory keyword arguments

def foo(a: 1, b: 2)

endkeyword arguments

Page 56: RedDot Ruby Conf 2014 - Dark side of ruby

Syntax

Page 57: RedDot Ruby Conf 2014 - Dark side of ruby

Syntaxdef foo(a, b) p a, b

end

Page 58: RedDot Ruby Conf 2014 - Dark side of ruby

Syntaxdef foo(a, b) p a, b

end

foo (1, 2)

Page 59: RedDot Ruby Conf 2014 - Dark side of ruby

Syntaxdef foo(a, b) p a, b

end

foo (1, 2)syntax error, unexpected

',', expecting ')'

Page 60: RedDot Ruby Conf 2014 - Dark side of ruby

Syntaxdef foo(a, b) p a, b

end

foo (1, 2)

foo(1, 2)

Page 61: RedDot Ruby Conf 2014 - Dark side of ruby

Syntaxdef foo(a, b) p a, b

end

foo (1, 2)

foo(1, 2)

Page 62: RedDot Ruby Conf 2014 - Dark side of ruby

Syntaxdef foo(a, b) p a, b

end

foo (1, 2)

foo(1, 2) syntax error, unexpected ',', expecting ')'

Page 63: RedDot Ruby Conf 2014 - Dark side of ruby

Syntax

Page 64: RedDot Ruby Conf 2014 - Dark side of ruby

Syntaxirb> a[1]

What is the data type of a ?

Page 65: RedDot Ruby Conf 2014 - Dark side of ruby

Syntaxirb> a[1]

a = [ 10, 11, 12] # Array

Page 66: RedDot Ruby Conf 2014 - Dark side of ruby

Syntaxirb> a[1]

a = [ 10, 11, 12] # Array

a = { 1 => "one" } # Hash

Page 67: RedDot Ruby Conf 2014 - Dark side of ruby

Syntaxirb> a[1]

a = [ 10, 11, 12] # Array

a = { 1 => "one" } # Hash

a = Proc.new { |e| p e }

Page 68: RedDot Ruby Conf 2014 - Dark side of ruby

Case Complexity

Page 69: RedDot Ruby Conf 2014 - Dark side of ruby

The Case Statementdef multiple_of(factor)! Proc.new {|p| p.modulo(factor).zero?}!end!!

number = 9!case number! when multiple_of(3)! puts "Multiple of 3"! when multiple_of(7)! puts "Multiple of 7"!end

Page 70: RedDot Ruby Conf 2014 - Dark side of ruby

The Case Statementdef multiple_of(factor)! Proc.new {|p| p.modulo(factor).zero?}!end!!

number = 9!case number! when multiple_of(3)! puts "Multiple of 3"! when multiple_of(7)! puts "Multiple of 7"!end

Page 71: RedDot Ruby Conf 2014 - Dark side of ruby

Behind every case is a ===number = 9!case number ! when multiple_of(3)

Proc.new {|p| p.modulo(3).zero?} === 9

Page 72: RedDot Ruby Conf 2014 - Dark side of ruby

Behind every case is a ===number = 9!case number ! when multiple_of(3)

Proc.new {|p| p.modulo(3).zero?} === 9

Page 73: RedDot Ruby Conf 2014 - Dark side of ruby

Behind every case is a ===number = 9!case number ! when multiple_of(3)

Proc.new {|p| p.modulo(3).zero?} === 9

Proc#=== is an alias to Proc#call.

Page 74: RedDot Ruby Conf 2014 - Dark side of ruby

Behind every case is a ===number = 9!case number ! when multiple_of(3)

Proc.new {|p| p.modulo(3).zero?} === 9

Proc.new { |p| ! p.modulo(3).zero?!}.call(9)

Proc#=== is an alias to Proc#call.

Page 75: RedDot Ruby Conf 2014 - Dark side of ruby

Override the === method to customise case

evaluation.

Page 76: RedDot Ruby Conf 2014 - Dark side of ruby

==, ===, eql?, equal?

http://www.flickr.com/photos/gak/2418146934/sizes/o/

Page 77: RedDot Ruby Conf 2014 - Dark side of ruby

==, ===, eql?, equal?

Page 78: RedDot Ruby Conf 2014 - Dark side of ruby

==, ===, eql?, equal?irb> 1 == 1.0

Page 79: RedDot Ruby Conf 2014 - Dark side of ruby

==, ===, eql?, equal?irb> 1 == 1.0=> true # generic equality

Page 80: RedDot Ruby Conf 2014 - Dark side of ruby

==, ===, eql?, equal?irb> 1 == 1.0=> true # generic equalityirb> 1 === 1.0

Page 81: RedDot Ruby Conf 2014 - Dark side of ruby

==, ===, eql?, equal?irb> 1 == 1.0=> true # generic equalityirb> 1 === 1.0=> true # case equality

Page 82: RedDot Ruby Conf 2014 - Dark side of ruby

==, ===, eql?, equal?irb> 1 == 1.0=> true # generic equalityirb> 1 === 1.0=> true # case equalityirb> 1.eql? 1.0

Page 83: RedDot Ruby Conf 2014 - Dark side of ruby

==, ===, eql?, equal?

=> false # alias of == except Numeric

irb> 1 == 1.0=> true # generic equalityirb> 1 === 1.0=> true # case equalityirb> 1.eql? 1.0

Page 84: RedDot Ruby Conf 2014 - Dark side of ruby

==, ===, eql?, equal?

=> false # alias of == except Numeric

irb> 1 == 1.0=> true # generic equalityirb> 1 === 1.0=> true # case equalityirb> 1.eql? 1.0

irb> 1.equal? 1.0

Page 85: RedDot Ruby Conf 2014 - Dark side of ruby

==, ===, eql?, equal?

=> false # alias of == except Numeric

irb> 1 == 1.0=> true # generic equalityirb> 1 === 1.0=> true # case equalityirb> 1.eql? 1.0

irb> 1.equal? 1.0=> false # object identity

Page 86: RedDot Ruby Conf 2014 - Dark side of ruby

==, ===, eql?, equal?

=> false # alias of == except Numeric

irb> 1 == 1.0=> true # generic equalityirb> 1 === 1.0=> true # case equalityirb> 1.eql? 1.0

irb> 1.equal? 1.0=> false # object identityirb> 'a'.equal? 'a'

Page 87: RedDot Ruby Conf 2014 - Dark side of ruby

==, ===, eql?, equal?

=> false # alias of == except Numeric

=> false # gotcha?

irb> 1 == 1.0=> true # generic equalityirb> 1 === 1.0=> true # case equalityirb> 1.eql? 1.0

irb> 1.equal? 1.0=> false # object identityirb> 'a'.equal? 'a'

Page 88: RedDot Ruby Conf 2014 - Dark side of ruby

==, ===, eql?, equal?

=> false # alias of == except Numeric

=> false # gotcha?

irb> 1 == 1.0=> true # generic equalityirb> 1 === 1.0=> true # case equalityirb> 1.eql? 1.0

irb> 1.equal? 1.0=> false # object identityirb> 'a'.equal? 'a'

irb> 1.equal? 1

Page 89: RedDot Ruby Conf 2014 - Dark side of ruby

==, ===, eql?, equal?

=> false # alias of == except Numeric

=> false # gotcha?

irb> 1 == 1.0=> true # generic equalityirb> 1 === 1.0=> true # case equalityirb> 1.eql? 1.0

irb> 1.equal? 1.0=> false # object identityirb> 'a'.equal? 'a'

=> true # gotcha?irb> 1.equal? 1

Page 90: RedDot Ruby Conf 2014 - Dark side of ruby

Object Ids & Fixnum

Page 91: RedDot Ruby Conf 2014 - Dark side of ruby

Object Ids & Fixnum

Fixnum * 2 + 1irb> 23 * 2 + 1 => 47 irb > 23.object_id => 47

Page 92: RedDot Ruby Conf 2014 - Dark side of ruby

Object Ids & Fixnum

Fixnum * 2 + 1irb> 23 * 2 + 1 => 47 irb > 23.object_id => 47

irb> (2**62 - 1).class => Fixnum irb> (2**62).class => Bignum

Page 93: RedDot Ruby Conf 2014 - Dark side of ruby

http://www.flickr.com/photos/miscdebris/6748016253/sizes/o/

Page 94: RedDot Ruby Conf 2014 - Dark side of ruby

3 Pulls for the Jackpotjackpot = lambda { |x, y, z| (x == y) == (x == z) } # 3 pulls pull = jackpot.curry[rand(5)] 2.times { pull = pull.curry[rand(5)] } !

p pull ? "Jackpot" : "Sucker!"

Page 95: RedDot Ruby Conf 2014 - Dark side of ruby

3 Pulls for the Jackpotjackpot = lambda { |x, y, z| (x == y) == (x == z) } # 3 pulls pull = jackpot.curry[rand(5)] 2.times { pull = pull.curry[rand(5)] } !

p pull ? "Jackpot" : "Sucker!"

Page 96: RedDot Ruby Conf 2014 - Dark side of ruby

3 Pulls for the Jackpotjackpot = lambda { |x, y, z| (x == y) == (x == z) } # 3 pulls pull = jackpot.curry[rand(5)] 2.times { pull = pull.curry[rand(5)] } !

p pull ? "Jackpot" : "Sucker!"

Page 97: RedDot Ruby Conf 2014 - Dark side of ruby

The curry recipe

• Return lambda till all parameters are passed.

• Evaluate the block if all parameters are passed.

pull = jackpot.curry[rand(5)] => #<Proc:0x007f9eec0990b0 (lambda)>

2.times { pull = pull.curry[rand(5)] } => true # or false

Page 98: RedDot Ruby Conf 2014 - Dark side of ruby

The curry recipe

• Return lambda till all parameters are passed.

• Evaluate the block if all parameters are passed.

pull = jackpot.curry[rand(5)] => #<Proc:0x007f9eec0990b0 (lambda)>

2.times { pull = pull.curry[rand(5)] } => true # or false

Page 99: RedDot Ruby Conf 2014 - Dark side of ruby

So! So you think you can tell…

Heaven from Hell- Pink Floyd

Page 100: RedDot Ruby Conf 2014 - Dark side of ruby

So! So you think you can tell…

Protected from Private

Page 101: RedDot Ruby Conf 2014 - Dark side of ruby

Private methodsclass Soldier private def ryan puts "Saving private ryan" end end class Movie < Soldier def name ryan end end

Page 102: RedDot Ruby Conf 2014 - Dark side of ruby

Private methodsclass Soldier private def ryan puts "Saving private ryan" end end class Movie < Soldier def name ryan end end

Page 103: RedDot Ruby Conf 2014 - Dark side of ruby

Private methodsclass Soldier private def ryan puts "Saving private ryan" end end class Movie < Soldier def name ryan end end

Private Methods are inherited!

Page 104: RedDot Ruby Conf 2014 - Dark side of ruby

class Base! include Mongoid::Document!end

The elusive include

Page 105: RedDot Ruby Conf 2014 - Dark side of ruby

class Base! include Mongoid::Document!end

The elusive include

Page 106: RedDot Ruby Conf 2014 - Dark side of ruby

Private method!Instance method !

Defined the class Module

class Base! include Mongoid::Document!end

The elusive include

Page 107: RedDot Ruby Conf 2014 - Dark side of ruby

Protected methods

Page 108: RedDot Ruby Conf 2014 - Dark side of ruby

Protected methods

Page 109: RedDot Ruby Conf 2014 - Dark side of ruby

Protected methods

• Work with objects not classes.

Page 110: RedDot Ruby Conf 2014 - Dark side of ruby

Protected methods

• Work with objects not classes.

• Invoke a protected method on another object in the same lineage

Page 111: RedDot Ruby Conf 2014 - Dark side of ruby

Protected methods

• Work with objects not classes.

• Invoke a protected method on another object in the same lineage

What the …

Page 112: RedDot Ruby Conf 2014 - Dark side of ruby

class Autobot def initialize(nick); @nick = nick; end !

protected attr_accessor :nick end !prime = Autobot.new("Optimus Prime") p prime.nick

Page 113: RedDot Ruby Conf 2014 - Dark side of ruby

class Autobot def initialize(nick); @nick = nick; end !

protected attr_accessor :nick end !prime = Autobot.new("Optimus Prime") p prime.nick

Page 114: RedDot Ruby Conf 2014 - Dark side of ruby

class Autobot def initialize(nick); @nick = nick; end !

protected attr_accessor :nick end !prime = Autobot.new("Optimus Prime") p prime.nick

protected method `nick' called for #<Autobot:0x007f92ba082330 @nick="Optimus Prime"> (NoMethodError)

Page 115: RedDot Ruby Conf 2014 - Dark side of ruby

class Autobot def fights(target) p "I am #{self.nick}" p "Kicking #{target.nick}'s ass" end protected attr_accessor :nick end !optimus = Autobot.new("Optimus Prime") megatron = Autobot.new('Megatron') !optimus.fights megatron

Page 116: RedDot Ruby Conf 2014 - Dark side of ruby

class Autobot def fights(target) p "I am #{self.nick}" p "Kicking #{target.nick}'s ass" end protected attr_accessor :nick end !optimus = Autobot.new("Optimus Prime") megatron = Autobot.new('Megatron') !optimus.fights megatron

Page 117: RedDot Ruby Conf 2014 - Dark side of ruby

class Autobot def fights(target) p "I am #{self.nick}" p "Kicking #{target.nick}'s ass" end protected attr_accessor :nick end !optimus = Autobot.new("Optimus Prime") megatron = Autobot.new('Megatron') !optimus.fights megatron

"I am Optimus Prime" "Kicking Megatron's ass"

Page 118: RedDot Ruby Conf 2014 - Dark side of ruby

class Autobot def fights(target) p "I am #{self.nick}" p "Kicking #{target.nick}'s ass" end protected attr_accessor :nick end !optimus = Autobot.new("Optimus Prime") megatron = Autobot.new('Megatron') !optimus.fights megatron

"I am Optimus Prime" "Kicking Megatron's ass"

Page 119: RedDot Ruby Conf 2014 - Dark side of ruby

Keywords in Ruby?

Page 120: RedDot Ruby Conf 2014 - Dark side of ruby

Keywords - hmm…class Serious def true false end def false true end end die = Serious.new p "seriously!" if die.false

Page 121: RedDot Ruby Conf 2014 - Dark side of ruby

Keywords - hmm…class Serious def true false end def false true end end die = Serious.new p "seriously!" if die.false

Page 122: RedDot Ruby Conf 2014 - Dark side of ruby

Keywords - hmm…class Serious def true false end def false true end end die = Serious.new p "seriously!" if die.false

stack too deep?

Page 123: RedDot Ruby Conf 2014 - Dark side of ruby

superlativeclass Search! def search! p "Default Search algorithm"! end!end!class KeywordSearch < Search ! def search(keyword:)! super! end!end!KeywordSearch.new.search(keyword: "Ruby")

Page 124: RedDot Ruby Conf 2014 - Dark side of ruby

superlativeclass Search! def search! p "Default Search algorithm"! end!end!class KeywordSearch < Search ! def search(keyword:)! super! end!end!KeywordSearch.new.search(keyword: "Ruby")

Page 125: RedDot Ruby Conf 2014 - Dark side of ruby

superlativeclass Search! def search! p "Default Search algorithm"! end!end!class KeywordSearch < Search ! def search(keyword:)! super! end!end!KeywordSearch.new.search(keyword: "Ruby")

Page 126: RedDot Ruby Conf 2014 - Dark side of ruby

superlativeclass Search! def search! p "Default Search algorithm"! end!end!class KeywordSearch < Search ! def search(keyword:)! super! end!end!KeywordSearch.new.search(keyword: "Ruby")

`search`: wrong number of arguments (1 for 0)

Page 127: RedDot Ruby Conf 2014 - Dark side of ruby

superlativeclass Search! def search! p "Default Search algorithm"! end!end!class KeywordSearch < Search ! def search(keyword:)! super()! end!end!KeywordSearch.new.search(keyword: "Ruby")

Page 128: RedDot Ruby Conf 2014 - Dark side of ruby

superlativeclass Search! def search! p "Default Search algorithm"! end!end!class KeywordSearch < Search ! def search(keyword:)! super()! end!end!KeywordSearch.new.search(keyword: "Ruby")

Page 129: RedDot Ruby Conf 2014 - Dark side of ruby

superlativeclass Search! def search! p "Default Search algorithm"! end!end!class KeywordSearch < Search ! def search(keyword:)! super()! end!end!KeywordSearch.new.search(keyword: "Ruby")

Page 130: RedDot Ruby Conf 2014 - Dark side of ruby

superlativeclass Search! def search! p "Default Search algorithm"! end!end!class KeywordSearch < Search ! def search(keyword:)! super()! end!end!KeywordSearch.new.search(keyword: "Ruby")

And we thought parenthesis for method invocation didn’t matter

Page 131: RedDot Ruby Conf 2014 - Dark side of ruby

Module mixins are funnymodule Superman! def fly; p "Superman: It's a bird"; end!end!!module Batman! def fly; p "Batman: Fly? Me?"; end!end!!module Ironman! def fly; p "Iroman: That's flying!"; end!end

Page 132: RedDot Ruby Conf 2014 - Dark side of ruby

Module mixins are funnymodule Superman! def fly; p "Superman: It's a bird"; end!end!!module Batman! def fly; p "Batman: Fly? Me?"; end!end!!module Ironman! def fly; p "Iroman: That's flying!"; end!end

Page 133: RedDot Ruby Conf 2014 - Dark side of ruby

Module mixins are funnyclass Tinyman! include Superman! include Batman! include Ironman!end!!Tinyman.new.fly

"Iroman: That's how you fly!"

Page 134: RedDot Ruby Conf 2014 - Dark side of ruby

Module mixins are funnyclass Tinyman! include Superman! include Batman! include Ironman!end!!Tinyman.new.fly

"Iroman: That's how you fly!"

Page 135: RedDot Ruby Conf 2014 - Dark side of ruby

Module Inheritance?module Superman! def fly; p "Superman: It's a bird"; end!end!!module Batman! def fly; p "Batman: Fly? Me?"; end!end!!module Ironman! def fly; super; p "Iroman: That's flying!"; end!end

Page 136: RedDot Ruby Conf 2014 - Dark side of ruby

Module Inheritance?module Superman! def fly; p "Superman: It's a bird"; end!end!!module Batman! def fly; p "Batman: Fly? Me?"; end!end!!module Ironman! def fly; super; p "Iroman: That's flying!"; end!end

Page 137: RedDot Ruby Conf 2014 - Dark side of ruby

Module Inheritance?module Superman! def fly; p "Superman: It's a bird"; end!end!!module Batman! def fly; p "Batman: Fly? Me?"; end!end!!module Ironman! def fly; super; p "Iroman: That's flying!"; end!end

"Batman: Fly? Me?”!"Iroman: That's flying!"

Page 138: RedDot Ruby Conf 2014 - Dark side of ruby

Dynamic Inheritance!class Tinyman! include Superman! include Batman! include Ironman!end

Page 139: RedDot Ruby Conf 2014 - Dark side of ruby

Dynamic Inheritance!class Tinyman! include Superman! include Batman! include Ironman!end

Page 140: RedDot Ruby Conf 2014 - Dark side of ruby

class Tinyman! include Superman! include Ironman! include Batman!end

Dynamic Inheritance!class Tinyman! include Superman! include Batman! include Ironman!end

Page 141: RedDot Ruby Conf 2014 - Dark side of ruby

class Tinyman! include Superman! include Ironman! include Batman!end

Dynamic Inheritance!class Tinyman! include Superman! include Batman! include Ironman!end

Page 142: RedDot Ruby Conf 2014 - Dark side of ruby

Cherry pick from Modules

module Megatron! def power! p "Megatron's super strength"! end!!

def evil! p 'Evil genius'! end!end

Page 143: RedDot Ruby Conf 2014 - Dark side of ruby

Cherry pick from Modules

module Megatron! def power! p "Megatron's super strength"! end!!

def evil! p 'Evil genius'! end!end

Page 144: RedDot Ruby Conf 2014 - Dark side of ruby

class Hanuman! include Megatron!end

Hanuman.new.power!# => "Megatron's super strength"!Hanuman.new.evil !# => "Evil genius" # Oh no!

Cherry pick from Modules

Page 145: RedDot Ruby Conf 2014 - Dark side of ruby

class Hanuman! include Megatron!end

Hanuman.new.power!# => "Megatron's super strength"!Hanuman.new.evil !# => "Evil genius" # Oh no!

Cherry pick from Modules

Page 146: RedDot Ruby Conf 2014 - Dark side of ruby

Cherry pick from Modulesclass Hanuman! def power! Megatron.instance_method(:power).! bind(self).call! end!end

Page 147: RedDot Ruby Conf 2014 - Dark side of ruby

Cherry pick from Modulesclass Hanuman! def power! Megatron.instance_method(:power).! bind(self).call! end!end

Page 148: RedDot Ruby Conf 2014 - Dark side of ruby

Cherry pick from Modulesclass Hanuman! def power! Megatron.instance_method(:power).! bind(self).call! end!end

Hanuman.new.power# => "Megatron's super strength"Hanuman.new.evil# => undefined method `evil’...>

Page 149: RedDot Ruby Conf 2014 - Dark side of ruby

That’s all Folks!

@gautamrege @joshsoftware

Page 150: RedDot Ruby Conf 2014 - Dark side of ruby

That’s all Folks!

@gautamrege @joshsoftware

since 2007