Metaprogramming in Ruby

114
Introduction DSL implementation Summary Metaprogramming in Ruby Domain specific languages Peter Vanbroekhoven [email protected] BRUG meeting October 3 2007 Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

description

Domain specific languages

Transcript of Metaprogramming in Ruby

Page 1: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Metaprogramming in RubyDomain specific languages

Peter [email protected]

BRUG meeting October 3 2007

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 2: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Outline

1 IntroductionMetaprogrammingRuby and Metaprogramming

2 DSL implementationChanging selfMissing constantsMissing methodsImplementing custom operators

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 3: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Outline

1 IntroductionMetaprogrammingRuby and Metaprogramming

2 DSL implementationChanging selfMissing constantsMissing methodsImplementing custom operators

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 4: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

MetaprogrammingRuby and Metaprogramming

Outline

1 IntroductionMetaprogrammingRuby and Metaprogramming

2 DSL implementationChanging selfMissing constantsMissing methodsImplementing custom operators

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 5: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

MetaprogrammingRuby and Metaprogramming

What Is Metaprogramming?

Programmingyour

programming

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 6: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

MetaprogrammingRuby and Metaprogramming

What Is Metaprogramming?

Metaprogrammingis a

good thing

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 7: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

MetaprogrammingRuby and Metaprogramming

The Deal With Metaprogramming

class ActiveRecord : : Basedef r e a d _ a t t r i b u t e ( attr_name )

@at t r ibu tes [ attr_name ]end

endclass MicrosoftCEO < ActiveRecord : : Baseend

b i l l = MicrosoftCEO . newmy_pocket << b i l l . r e a d _ a t t r i b u t e ( "money" )

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 8: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

MetaprogrammingRuby and Metaprogramming

The Deal With Metaprogramming

class MicrosoftCEO < ActiveRecord : : Basedef money

@at t r ibu tes [ "money" ]end

end

b i l l = MicrosoftCEO . newmy_pocket << b i l l . money

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 9: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

MetaprogrammingRuby and Metaprogramming

The Deal With Metaprogramming

class MicrosoftCEO < ActiveRecord : : Basedef money

@at t r ibu tes [ "money" ]enddef house

@at t r ibu tes [ " house " ]enddef car

@at t r ibu tes [ " car " ]end

end

b i l l = MicrosoftCEO . newmy_pocket << b i l l . money << b i l l . house << b i l l . car

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 10: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

MetaprogrammingRuby and Metaprogramming

The Deal With Metaprogramming

class MicrosoftCEO < ActiveRecord : : Base[ "money" , " house " , " car " ] . each do | f |

define_method ( f ) { @at t r ibu tes [ f ] }end

end

b i l l = MicrosoftCEO . newmy_pocket << b i l l . money << b i l l . house << b i l l . car

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 11: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

MetaprogrammingRuby and Metaprogramming

Examples of metaprogramming

Java compilerRuby interpreterFirefox browserRuby on Rails

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 12: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

MetaprogrammingRuby and Metaprogramming

Examples of metaprogramming

Java compilerRuby interpreterFirefox browserRuby on Rails

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 13: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

MetaprogrammingRuby and Metaprogramming

Examples of metaprogramming

Java compilerRuby interpreterFirefox browserRuby on Rails

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 14: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

MetaprogrammingRuby and Metaprogramming

Examples of metaprogramming

Java compilerRuby interpreterFirefox browserRuby on Rails

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 15: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

MetaprogrammingRuby and Metaprogramming

Examples of metaprogramming

Java compilerRuby interpreterFirefox browserRuby on Rails

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 16: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

MetaprogrammingRuby and Metaprogramming

Domain specific languages

def i s _ s t u f f _ c h a r ( c )( c >= ?a && c <= ?z ) | | ( c >= ?A && c <= ?Z) | |( c >= ?0 && c <= ?9) | | c == ?_

enddef f i n d _ s t u f f ( s t r )

r e s u l t = [ ] ; i = 0 ; while i < s t r . l eng ths t a r t = i ; i += 1 while i s _ s t u f f _ c h a r ( s t r [ i ] )i f s t a r t != i && s t r [ i ] == ’@’

a t = i ; i += 1i += 1 while i s _ s t u f f _ c h a r ( s t r [ i ] )r e s u l t << s t r [ s t a r t . . . i ] i f at != i

end ; i += 1 ; endr e s u l t ; end

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 17: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

MetaprogrammingRuby and Metaprogramming

Domain specific languages

def f i nd_ema i l s ( s t r )s t r . scan ( / \w+@\w+ / )

end

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 18: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

MetaprogrammingRuby and Metaprogramming

Domain specific languages

musical notes guitar chords

DSLsare

everywhere

traffic signs Ruby

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 19: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

MetaprogrammingRuby and Metaprogramming

Domain specific languages

musical notes

''PPPPPPPPPPPP

guitar chords

DSLsare

everywhere

traffic signs Ruby

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 20: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

MetaprogrammingRuby and Metaprogramming

Domain specific languages

musical notes

''PPPPPPPPPPPP guitar chords

wwoooooooooooo

DSLsare

everywhere

traffic signs Ruby

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 21: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

MetaprogrammingRuby and Metaprogramming

Domain specific languages

musical notes

''PPPPPPPPPPPP guitar chords

wwoooooooooooo

DSLsare

everywhere

traffic signs

77nnnnnnnnnnnn

Ruby

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 22: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

MetaprogrammingRuby and Metaprogramming

Domain specific languages

musical notes

''PPPPPPPPPPPP guitar chords

wwoooooooooooo

DSLsare

everywhere

traffic signs

77nnnnnnnnnnnnRuby

ggOOOOOOOOOOOO

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 23: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

MetaprogrammingRuby and Metaprogramming

Outline

1 IntroductionMetaprogrammingRuby and Metaprogramming

2 DSL implementationChanging selfMissing constantsMissing methodsImplementing custom operators

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 24: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

MetaprogrammingRuby and Metaprogramming

Metaprogramming in Java

public Plug in c rea te_p lug in ( S t r i n g name,S t r i n g [ ] keys , S t r i n g [ ] values )

throws . . . {Class c = Class . forName (name ) ;Class s = Class . forName ( " [ L java . lang . S t r i n g ; " ) ;Const ruc tor co = c . ge tCons t ruc to r ( s , s ) ;return ( P lug in ) co . newInstance ( keys , values ) ;

}

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 25: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

MetaprogrammingRuby and Metaprogramming

Metaprogramming in Ruby

def c rea te_p lug in (name, keys , values )Object . const_get (name ) . new( keys , values )

end

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 26: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

MetaprogrammingRuby and Metaprogramming

Comparison

Metaprogramming in Rubyis

easy

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 27: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

MetaprogrammingRuby and Metaprogramming

Comparison

Metaprogramming in Javais

hard

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 28: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

MetaprogrammingRuby and Metaprogramming

DSLs in Ruby

f i r s t 1 , f i r s t 2 , l a s t = ’ pe ter ’ , ’ glenn ’ , ’ v\% ’banks = connect ion . execute ( "

SELECT b . nameFROM customer AS c , bank AS b , account AS aWHERE ( c . f i r s tname = ’#{first1} ’ OR

c . f i r s tname = ’#{first2} ’ ) ANDc . lastname LIKE ’#{last} ’ ANDa . owner = c . i d ANDa . bank = b . i d

" )

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 29: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

MetaprogrammingRuby and Metaprogramming

DSLs in Ruby : ActiveRecord

Bank . f i n d (: a l l ,: i nc lude => { : accounts => : customer } ,: cond i t i ons => [

" ( customers . f i r s t_name = ? ORcustomers . f i r s t_name = ?) AND

customers . last_name LIKE ? " ," f i r s t 1 " , " f i r s t 2 " , " l a s t " ]

) . map { | b | b . name }

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 30: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

MetaprogrammingRuby and Metaprogramming

DSLs in Ruby : my own DSL

f i r s t 1 , f i r s t 2 , l a s t = ’ pe ter ’ , ’ glenn ’ , / \ Av /banks = query do

from : c => Customer , : b => Bank , : a => Accounts e l e c t b . namewhere ( ( c . f i r s tname == f i r s t 1 ) |

( c . f i r s tname == f i r s t 2 ) ) &( c . lastname =~ l a s t ) &( a . owner == c ) &( a . bank == b )

end

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 31: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

MetaprogrammingRuby and Metaprogramming

DSLs in Ruby : my own DSL

f i r s t 1 , f i r s t 2 , l a s t = ’ pe ter ’ , ’ glenn ’ , / \ Av /banks = query do

from : a => Accounts e l e c t a . bank . namewhere ( ( a . owner . f i r s tname == f i r s t 1 ) |

( a . owner . f i r s tname == f i r s t 2 ) ) &( a . owner . lastname =~ l a s t )

end

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 32: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

MetaprogrammingRuby and Metaprogramming

DSLs in Ruby : my own DSL

f i r s t 1 , f i r s t 2 , l a s t = ’ pe ter ’ , ’ glenn ’ , / \ Av /banks = query do

from : a => Account

c = a . owner

s e l e c t a . bank . namewhere ( ( c . f i r s tname == f i r s t 1 ) |

( c . f i r s tname == f i r s t 2 ) ) &( c . lastname =~ l a s t )

end

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 33: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

MetaprogrammingRuby and Metaprogramming

DSLs in Ruby

easy to build familiar syntax

A Ruby DSLis just

plain Ruby

abstraction

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 34: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

MetaprogrammingRuby and Metaprogramming

DSLs in Ruby

easy to build

''OOOOOOOOOOO

familiar syntax

A Ruby DSLis just

plain Ruby

abstraction

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 35: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

MetaprogrammingRuby and Metaprogramming

DSLs in Ruby

easy to build

''OOOOOOOOOOO familiar syntax

wwnnnnnnnnnnnn

A Ruby DSLis just

plain Ruby

abstraction

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 36: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

MetaprogrammingRuby and Metaprogramming

DSLs in Ruby

easy to build

''OOOOOOOOOOO familiar syntax

wwnnnnnnnnnnnn

A Ruby DSLis just

plain Ruby

abstraction

OO

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 37: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

MetaprogrammingRuby and Metaprogramming

What I’ll Teach You

f i r s t 1 , f i r s t 2 , l a s t = ’ pe ter ’ , ’ glenn ’ , / \ Av /banks = query do

from : c => Customer , : b => Bank , : a => Accounts e l e c t b . namewhere ( ( c . f i r s tname == f i r s t 1 ) |

( c . f i r s tname == f i r s t 2 ) ) &( c . lastname =~ l a s t ) &( a . owner == c ) &( a . bank == b )

end

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 38: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Changing selfMissing constantsMissing methodsImplementing custom operators

Outline

1 IntroductionMetaprogrammingRuby and Metaprogramming

2 DSL implementationChanging selfMissing constantsMissing methodsImplementing custom operators

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 39: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Changing selfMissing constantsMissing methodsImplementing custom operators

What is self?

instancevariables

dotlessmethods

selfis the

current object

classvariables

changed bymethod calls,class defs

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 40: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Changing selfMissing constantsMissing methodsImplementing custom operators

What is self?

instancevariables

''OOOOOOOOOOO

dotlessmethods

selfis the

current object

classvariables

changed bymethod calls,class defs

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 41: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Changing selfMissing constantsMissing methodsImplementing custom operators

What is self?

instancevariables

''OOOOOOOOOOO

dotlessmethods

vvnnnnnnnnnnn

selfis the

current object

classvariables

changed bymethod calls,class defs

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 42: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Changing selfMissing constantsMissing methodsImplementing custom operators

What is self?

instancevariables

''OOOOOOOOOOO

dotlessmethods

vvnnnnnnnnnnn

selfis the

current object

classvariables

88qqqqqqqqqqqq

changed bymethod calls,class defs

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 43: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Changing selfMissing constantsMissing methodsImplementing custom operators

What is self?

instancevariables

''OOOOOOOOOOO

dotlessmethods

vvnnnnnnnnnnn

selfis the

current object

classvariables

88qqqqqqqqqqqq changed bymethod calls,class defs

ggOOOOOOOOOOO

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 44: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Changing selfMissing constantsMissing methodsImplementing custom operators

What is self?

banks = query do. . .

end

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 45: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Changing selfMissing constantsMissing methodsImplementing custom operators

What is self?

banks = se l f . query do. . .

end

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 46: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Changing selfMissing constantsMissing methodsImplementing custom operators

What is self?

# Top l e v e lp se l f # => mainp se l f . class # => Object

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 47: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Changing selfMissing constantsMissing methodsImplementing custom operators

What is self?

banks = se l f . query do. . .

end

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 48: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Changing selfMissing constantsMissing methodsImplementing custom operators

The Kernel module

puts raise

Kernel

require eval

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 49: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Changing selfMissing constantsMissing methodsImplementing custom operators

The Kernel module

puts

''OOOOOOOOOOO

raise

Kernel

require eval

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 50: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Changing selfMissing constantsMissing methodsImplementing custom operators

The Kernel module

puts

''OOOOOOOOOOO raise

xxqqqqqqqqqqq

Kernel

require eval

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 51: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Changing selfMissing constantsMissing methodsImplementing custom operators

The Kernel module

puts

''OOOOOOOOOOO raise

xxqqqqqqqqqqq

Kernelrequire

77ooooooooooo

eval

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 52: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Changing selfMissing constantsMissing methodsImplementing custom operators

The Kernel module

puts

''OOOOOOOOOOO raise

xxqqqqqqqqqqq

Kernelrequire

77oooooooooooeval

ffMMMMMMMMMMM

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 53: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Changing selfMissing constantsMissing methodsImplementing custom operators

The query method

module Kerneldef query

yie ld # Ca l l the blockend

end

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 54: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Changing selfMissing constantsMissing methodsImplementing custom operators

Changing self

banks = query dofrom : c => Customer , : b => Bank , : a => Account. . .

end

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 55: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Changing selfMissing constantsMissing methodsImplementing custom operators

Changing self

banks = query dose l f . from : c => Customer , . . .. . .

end

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 56: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Changing selfMissing constantsMissing methodsImplementing custom operators

Changing self

banks = query dop se l f # => main

end

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 57: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Changing selfMissing constantsMissing methodsImplementing custom operators

Changing self

banks = query dose l f . from : c => Customer , . . .. . .

end

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 58: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Changing selfMissing constantsMissing methodsImplementing custom operators

Changing self

Sometimeswe want tochange self

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 59: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Changing selfMissing constantsMissing methodsImplementing custom operators

Changing self

class Queryendmodule Kernel

def query (& b lk )Query . new . ins tance_eva l (& b lk )

endend

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 60: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Changing selfMissing constantsMissing methodsImplementing custom operators

Changing self

banks = query dop se l f # => #<Query :0 xb7cc4adc>

end

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 61: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Changing selfMissing constantsMissing methodsImplementing custom operators

Changing self

instance_evalchanges self

for the duration of a block

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 62: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Changing selfMissing constantsMissing methodsImplementing custom operators

Changing self

class Querydef i n i t i a l i z e

@from = { }enddef from (map)

@from = mapend

end

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 63: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Changing selfMissing constantsMissing methodsImplementing custom operators

Changing self

banks = query dofrom : c => Customer , : b => Bank , : a => Accountp se l f # => #<Query :0 xb7cc4adc# @from = { : b=>Bank , : a=>Account , : c=>Customer } >

end

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 64: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Changing selfMissing constantsMissing methodsImplementing custom operators

Outline

1 IntroductionMetaprogrammingRuby and Metaprogramming

2 DSL implementationChanging selfMissing constantsMissing methodsImplementing custom operators

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 65: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Changing selfMissing constantsMissing methodsImplementing custom operators

Lazy class loading

Railscan do

lazy class loading

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 66: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Changing selfMissing constantsMissing methodsImplementing custom operators

Lazy class loading

test.rb

# requ i re ’ brug ’BRUG. new( Time . now)

brug.rb

class BRUGdef i n i t i a l i z e ( t ime )

@time = t imeend

end

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 67: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Changing selfMissing constantsMissing methodsImplementing custom operators

Constant lookup

BRUG.new

n = Module.nesting + [Object]

find BRUG in n

return BRUG n [0]. const_missing(:BRUG)

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 68: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Changing selfMissing constantsMissing methodsImplementing custom operators

Constant lookup

BRUG.new

��n = Module.nesting + [Object]

find BRUG in n

return BRUG n [0]. const_missing(:BRUG)

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 69: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Changing selfMissing constantsMissing methodsImplementing custom operators

Constant lookup

BRUG.new

��n = Module.nesting + [Object]

��find BRUG in n

return BRUG n [0]. const_missing(:BRUG)

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 70: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Changing selfMissing constantsMissing methodsImplementing custom operators

Constant lookup

BRUG.new

��n = Module.nesting + [Object]

��find BRUG in n

found

zzuuuuuuuuuuuuuuuuuuuu

return BRUG

n [0]. const_missing(:BRUG)

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 71: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Changing selfMissing constantsMissing methodsImplementing custom operators

Constant lookup

BRUG.new

��n = Module.nesting + [Object]

��find BRUG in n

found

zzuuuuuuuuuuuuuuuuuuuu

not found

%%KKKKKKKKKKKKKKKKKKKKK

return BRUG n [0]. const_missing(:BRUG)

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 72: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Changing selfMissing constantsMissing methodsImplementing custom operators

Module.nesting

class Amodule B

def mModule . nes t ing # => [A : : B, A ]

endModule . nes t ing # => [A : : B, A ]

endendModule . nes t ing # => [ ]def A.m

Module . nes t ing # => [ ]end

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 73: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Changing selfMissing constantsMissing methodsImplementing custom operators

Lazy class loading

banks = query dofrom : c => Customer , : b => Bank , : a => Accountp Module . nes t ing + [ Object ] # => [ Object ]. . .

end

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 74: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Changing selfMissing constantsMissing methodsImplementing custom operators

Lazy loading

def Object . const_missing ( c id )f i l e = f i n d _ f i l e ( c id )requ i re f i l econst_get ( c id )

end

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 75: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Changing selfMissing constantsMissing methodsImplementing custom operators

Lazy class loading

def Object . const_missing ( c id )f i l e = f i n d _ f i l e ( c id )requ i re f i l ei f const_def ined? c id

const_get ( c id )else

# c a l l o ld const_missingend

end

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 76: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Changing selfMissing constantsMissing methodsImplementing custom operators

Lazy class loading

def Object . const_missing ( c id )f i l e = f i n d _ f i l e ( c id )requ i re f i l ei f const_def ined? c id

const_get ( c id )else

# Class < Modulesuper

endend

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 77: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Changing selfMissing constantsMissing methodsImplementing custom operators

Lazy class loading

Lazy class loadingis

freakingly easy

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 78: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Changing selfMissing constantsMissing methodsImplementing custom operators

Outline

1 IntroductionMetaprogrammingRuby and Metaprogramming

2 DSL implementationChanging selfMissing constantsMissing methodsImplementing custom operators

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 79: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Changing selfMissing constantsMissing methodsImplementing custom operators

Handling b.name

banks = query do. . .s e l e c t b . name. . .

end

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 80: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Changing selfMissing constantsMissing methodsImplementing custom operators

Handling b.name

banks = query do. . .s e l e c t se l f . b . name. . .

end

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 81: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Changing selfMissing constantsMissing methodsImplementing custom operators

Handling b.name

class Querydef b

. . .end

end

banks = query do. . .s e l e c t se l f . b . name. . .

end

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 82: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Changing selfMissing constantsMissing methodsImplementing custom operators

Handling b.name

Can we

avoidmass method definition

?

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 83: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Changing selfMissing constantsMissing methodsImplementing custom operators

Missing methods

self .b.name

self .b.name self .method_missing(:b)

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 84: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Changing selfMissing constantsMissing methodsImplementing custom operators

Missing methods

self .b.name

b found

{{wwwwwwwwwwwwwwwwwww

self .b.name

self .method_missing(:b)

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 85: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Changing selfMissing constantsMissing methodsImplementing custom operators

Missing methods

self .b.name

b found

{{wwwwwwwwwwwwwwwwwww

b not found

$$JJJJJJJJJJJJJJJJJJJJ

self .b.name self .method_missing(:b)

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 86: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Changing selfMissing constantsMissing methodsImplementing custom operators

Implementing Query#method_missing

banks = query do. . .p se l f # => #<Query :0 xb7cf5dd4 >s e l e c t se l f . b . name. . .

end

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 87: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Changing selfMissing constantsMissing methodsImplementing custom operators

Implementing Query#method_missing

class Querydef method_missing ( mid , ∗args )

i f args . leng th == 0 && @from [m]Var iab leExpress ion . new(m)

elsesuper

endend

end

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 88: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Changing selfMissing constantsMissing methodsImplementing custom operators

Implementing Query#method_missing

class Var iab leExpress ion < Expression

a t t r _ r e a d e r : varname

def i n i t i a l i z e ( varname )@varname = varname

end

end

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 89: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Changing selfMissing constantsMissing methodsImplementing custom operators

Alternative implementation

class Querya l ias old_mm method_missingdef method_missing (m, ∗args )

i f args . leng th == 0 && @from [m]Var iab leExpress ion . new(m)

elseold_mm (m, ∗args )

endend

end

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 90: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Changing selfMissing constantsMissing methodsImplementing custom operators

Implementing Expression#method_missing

banks = query do. . .# s e l e c t bs e l e c t b . name. . .

end

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 91: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Changing selfMissing constantsMissing methodsImplementing custom operators

Implementing Expression#method_missing

class Expression

def method_missing (m, ∗args )i f args . leng th == 0

Fie ldExpress ion . new( sel f , m)else

superend

end

end

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 92: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Changing selfMissing constantsMissing methodsImplementing custom operators

Implementing Expression#method_missing

class Fie ldExpress ion < Expressiondef i n i t i a l i z e ( expression , f i e l d )

@expression , @f ie ld = expression , f i e l dend

end

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 93: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Changing selfMissing constantsMissing methodsImplementing custom operators

Summary

YES,we can

avoidmass method definition

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 94: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Changing selfMissing constantsMissing methodsImplementing custom operators

Outline

1 IntroductionMetaprogrammingRuby and Metaprogramming

2 DSL implementationChanging selfMissing constantsMissing methodsImplementing custom operators

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 95: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Changing selfMissing constantsMissing methodsImplementing custom operators

Oerator overloading

banks = query do. . .where ( ( c . f i r s tname == f i r s t 1 ) |

( c . f i r s tname == f i r s t 2 ) ) &( c . lastname =~ l a s t ) &( a . owner == c ) &( a . bank == b )

end

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 96: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Changing selfMissing constantsMissing methodsImplementing custom operators

Operator overloading

Operatorsare just

methods

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 97: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Changing selfMissing constantsMissing methodsImplementing custom operators

Operator overloading

banks = query do. . .where ( ( c . f i r s tname .==( f i r s t 1 ) . | (

c . f i r s tname .==( f i r s t 2 ) ) . & (c . lastname .=~( l a s t ) . & (a . owner == c ) . & ( a . bank .==( b ) )

end

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 98: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Changing selfMissing constantsMissing methodsImplementing custom operators

Implementing operator overloading

class Expressiondef ==( o ther )

BinaryOpExpression . new( sel f , other , ’ = ’ )enddef &( other )

BinaryOpExpression . new( sel f , other , ’AND ’ )end. . .

end

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 99: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Changing selfMissing constantsMissing methodsImplementing custom operators

Implementing operator overloading

class BinaryOpExpression < Expression

def i n i t i a l i z e ( expr1 , expr2 , op )@expr1 , @expr2 , @op = expr1 , expr2 , op

end

end

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 100: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Changing selfMissing constantsMissing methodsImplementing custom operators

Limitations operator overloading

&&, ||, !are

NOTmethods

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 101: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Changing selfMissing constantsMissing methodsImplementing custom operators

Summary

but ...

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 102: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Changing selfMissing constantsMissing methodsImplementing custom operators

Limitations operator overloading

Operator overloadingis

child’s play

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 103: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Changing selfMissing constantsMissing methodsImplementing custom operators

Wrapping up the example

banks = query do. . .where . . .

end

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 104: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Changing selfMissing constantsMissing methodsImplementing custom operators

Wrapping up the example

class Query

def where ( cond )@where = cond

end

end

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 105: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Changing selfMissing constantsMissing methodsImplementing custom operators

Wrapping up the example

class Query

def t o_sq l"SELECT #{ r e t u r n _ l i s t } " \"FROM #{ t a b l e _ l i s t } " \"WHERE #{ cond i t i on_expr } "

end

end

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 106: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Changing selfMissing constantsMissing methodsImplementing custom operators

Wrapping up the example

class Querydef t a b l e _ l i s t

@from .map { | v , t | " #{ t } AS #{ v } " } . j o i n ( " , " )end

def r e t u r n _ l i s t@select .map { | r | r . t o_sq l } . j o i n ( " , " )

end

def cond i t i on_expr@where . to_sq l

endend

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 107: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Changing selfMissing constantsMissing methodsImplementing custom operators

Wrapping up the example

f i r s t 1 , f i r s t 2 , l a s t = ’ pe ter ’ , ’ glenn ’ , / \ Av /banks = query do

from : c => Customer , : b => Bank , : a => Accounts e l e c t b . namewhere ( ( c . f i r s tname == f i r s t 1 ) |

( c . f i r s tname == f i r s t 2 ) ) &( c . lastname =~ l a s t ) &( a . owner == c ) &( a . bank == b )

end

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 108: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Summary

Ruby has very natural metaprogramming facilitiesRuby allows building DSLs in pure RubyMetaporgramming made easy

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 109: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Summary

Ruby has very natural metaprogramming facilitiesRuby allows building DSLs in pure RubyMetaporgramming made easy

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 110: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Summary

Ruby has very natural metaprogramming facilitiesRuby allows building DSLs in pure RubyMetaporgramming made easy

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 111: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Further reading

why’s (poignant) guide to Rubyhttp://poignantguide.net/ruby/http://poignantguide.net/ruby/chapter-6.html

Ruby for Railshttp://www.manning.com/black/

Programming Rubyhttp://www.rubycentral.com/pickaxe/http://www.pragmaticprogrammer.com/title/ruby/

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 112: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Further reading

why’s (poignant) guide to Rubyhttp://poignantguide.net/ruby/http://poignantguide.net/ruby/chapter-6.html

Ruby for Railshttp://www.manning.com/black/

Programming Rubyhttp://www.rubycentral.com/pickaxe/http://www.pragmaticprogrammer.com/title/ruby/

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 113: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

Further reading

why’s (poignant) guide to Rubyhttp://poignantguide.net/ruby/http://poignantguide.net/ruby/chapter-6.html

Ruby for Railshttp://www.manning.com/black/

Programming Rubyhttp://www.rubycentral.com/pickaxe/http://www.pragmaticprogrammer.com/title/ruby/

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby

Page 114: Metaprogramming in Ruby

IntroductionDSL implementation

Summary

REAL Summary

Ruby rocks!!!

Peter Vanbroekhoven [email protected] Metaprogramming in Ruby