Metaprogramming in Ruby

2,448 views

Published on

Domain specific languages

Published in: Technology, Education
0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
2,448
On SlideShare
0
From Embeds
0
Number of Embeds
33
Actions
Shares
0
Downloads
152
Comments
0
Likes
2
Embeds 0
No embeds

No notes for slide

Metaprogramming in Ruby

  1. 1. Introduction DSL implementation Summary Metaprogramming in Ruby Domain specific languages Peter Vanbroekhoven peter@xaop.com BRUG meeting October 3 2007 Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  2. 2. Introduction DSL implementation Summary Outline Introduction 1 Metaprogramming Ruby and Metaprogramming DSL implementation 2 Changing self Missing constants Missing methods Implementing custom operators Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  3. 3. Introduction DSL implementation Summary Outline Introduction 1 Metaprogramming Ruby and Metaprogramming DSL implementation 2 Changing self Missing constants Missing methods Implementing custom operators Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  4. 4. Introduction Metaprogramming DSL implementation Ruby and Metaprogramming Summary Outline Introduction 1 Metaprogramming Ruby and Metaprogramming DSL implementation 2 Changing self Missing constants Missing methods Implementing custom operators Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  5. 5. Introduction Metaprogramming DSL implementation Ruby and Metaprogramming Summary What Is Metaprogramming? Programming your programming Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  6. 6. Introduction Metaprogramming DSL implementation Ruby and Metaprogramming Summary What Is Metaprogramming? Metaprogramming is a good thing Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  7. 7. Introduction Metaprogramming DSL implementation Ruby and Metaprogramming Summary The Deal With Metaprogramming class ActiveRecord : : Base def r e a d _ a t t r i b u t e ( attr_name ) @ a t t r i b u t e s [ attr_name ] end end class MicrosoftCEO < ActiveRecord : : Base end b i l l = MicrosoftCEO . new my_pocket << b i l l . r e a d _ a t t r i b u t e ( quot; money quot; ) Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  8. 8. Introduction Metaprogramming DSL implementation Ruby and Metaprogramming Summary The Deal With Metaprogramming class MicrosoftCEO < ActiveRecord : : Base def money @ a t t r i b u t e s [ quot; money quot; ] end end b i l l = MicrosoftCEO . new my_pocket << b i l l . money Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  9. 9. Introduction Metaprogramming DSL implementation Ruby and Metaprogramming Summary The Deal With Metaprogramming class MicrosoftCEO < ActiveRecord : : Base def money @ a t t r i b u t e s [ quot; money quot; ] end def house @ a t t r i b u t e s [ quot; house quot; ] end def c a r @attributes [ quot; car quot; ] end end b i l l = MicrosoftCEO . new my_pocket << b i l l . money << b i l l . house << b i l l . c a r Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  10. 10. Introduction Metaprogramming DSL implementation Ruby and Metaprogramming Summary The Deal With Metaprogramming class MicrosoftCEO < ActiveRecord : : Base [ quot; money quot; , quot; house quot; , quot; c a r quot; ] . each do | f | define_method ( f ) { @ a t t r i b u t e s [ f ] } end end b i l l = MicrosoftCEO . new my_pocket << b i l l . money << b i l l . house << b i l l . c a r Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  11. 11. Introduction Metaprogramming DSL implementation Ruby and Metaprogramming Summary Examples of metaprogramming Java compiler Ruby interpreter Firefox browser Ruby on Rails Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  12. 12. Introduction Metaprogramming DSL implementation Ruby and Metaprogramming Summary Examples of metaprogramming Java compiler Ruby interpreter Firefox browser Ruby on Rails Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  13. 13. Introduction Metaprogramming DSL implementation Ruby and Metaprogramming Summary Examples of metaprogramming Java compiler Ruby interpreter Firefox browser Ruby on Rails Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  14. 14. Introduction Metaprogramming DSL implementation Ruby and Metaprogramming Summary Examples of metaprogramming Java compiler Ruby interpreter Firefox browser Ruby on Rails Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  15. 15. Introduction Metaprogramming DSL implementation Ruby and Metaprogramming Summary Examples of metaprogramming Java compiler Ruby interpreter Firefox browser Ruby on Rails Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  16. 16. Introduction Metaprogramming DSL implementation Ruby and Metaprogramming Summary 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 == ?_ end def 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 e n g t h s 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 += 1 i += 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 a t ! = i end ; i += 1 ; end r e s u l t ; end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  17. 17. Introduction Metaprogramming DSL implementation Ruby and Metaprogramming Summary Domain specific languages def f i n d _ e m a i l s ( s t r ) s t r . scan ( / w+@ w+ / ) end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  18. 18. Introduction Metaprogramming DSL implementation Ruby and Metaprogramming Summary Domain specific languages DSLs are everywhere Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  19. 19. Introduction Metaprogramming DSL implementation Ruby and Metaprogramming Summary Domain specific languages musical notes PP PPP PPP PPP P' DSLs are everywhere Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  20. 20. Introduction Metaprogramming DSL implementation Ruby and Metaprogramming Summary Domain specific languages guitar chords musical notes PP oo PPP ooo PPP ooo PPP o wooo P' DSLs are everywhere Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  21. 21. Introduction Metaprogramming DSL implementation Ruby and Metaprogramming Summary Domain specific languages guitar chords musical notes PP oo PPP ooo PPP ooo PPP o wooo P' DSLs are everywhere 7 nnn nn nnn nnn n traffic signs Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  22. 22. Introduction Metaprogramming DSL implementation Ruby and Metaprogramming Summary Domain specific languages guitar chords musical notes PP oo PPP ooo PPP ooo PPP o wooo P' DSLs are everywhereOOO gO 7 nnn OOO nn nnn OOO nnn OO n Ruby traffic signs Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  23. 23. Introduction Metaprogramming DSL implementation Ruby and Metaprogramming Summary Outline Introduction 1 Metaprogramming Ruby and Metaprogramming DSL implementation 2 Changing self Missing constants Missing methods Implementing custom operators Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  24. 24. Introduction Metaprogramming DSL implementation Ruby and Metaprogramming Summary Metaprogramming in Java public P l u g i n c r e a t e _ p l u g i n ( S t r i n g name , S t r i n g [ ] keys , S t r i n g [ ] v a l u e s ) throws . . . { Class c = Class . forName ( name ) ; Class s = Class . forName ( quot; [ L j a v a . l a n g . S t r i n g ; quot; ) ; C o n s t r u c t o r co = c . g e t C o n s t r u c t o r ( s , s ) ; r e t u r n ( P l u g i n ) co . newInstance ( keys , v a l u e s ) ; } Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  25. 25. Introduction Metaprogramming DSL implementation Ruby and Metaprogramming Summary Metaprogramming in Ruby def c r e a t e _ p l u g i n ( name , keys , v a l u e s ) O b j e c t . c o n s t _ g e t ( name ) . new ( keys , v a l u e s ) end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  26. 26. Introduction Metaprogramming DSL implementation Ruby and Metaprogramming Summary Comparison Metaprogramming in Ruby is easy Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  27. 27. Introduction Metaprogramming DSL implementation Ruby and Metaprogramming Summary Comparison Metaprogramming in Java is hard Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  28. 28. Introduction Metaprogramming DSL implementation Ruby and Metaprogramming Summary DSLs in Ruby f i r s t 1 , f i r s t 2 , l a s t = ’ p e t e r ’ , ’ glenn ’ , ’ v% ’ banks = c o n n e c t i o n . execute ( quot; SELECT b . name FROM customer AS c , bank AS b , account AS a WHERE ( c . f i r s t n a m e = ’ #{first1} ’ OR c . f i r s t n a m e = ’ #{first2} ’ ) AND c . lastname LIKE ’ #{last} ’ AND a . owner = c . i d AND a . bank = b . i d quot;) Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  29. 29. Introduction Metaprogramming DSL implementation Ruby and Metaprogramming Summary DSLs in Ruby : ActiveRecord Bank . f i n d ( : all , : i n c l u d e => { : accounts => : customer } , : c o n d i t i o n s => [ quot; ( customers . f i r s t _ n a m e = ? OR customers . f i r s t _ n a m e = ? ) AND customers . last_name LIKE ? quot; , quot; first1 quot; , quot; first2 quot; , quot; last quot; ] ) . map { | b | b . name } Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  30. 30. Introduction Metaprogramming DSL implementation Ruby and Metaprogramming Summary DSLs in Ruby : my own DSL f i r s t 1 , f i r s t 2 , l a s t = ’ p e t e r ’ , ’ glenn ’ , / Av / banks = query do from : c => Customer , : b => Bank , : a => Account s e l e c t b . name where ( ( c . f i r s t n a m e == f i r s t 1 ) | ( c . f i r s t n a m e == f i r s t 2 ) ) & ( c . lastname =~ l a s t ) & ( a . owner == c ) & ( a . bank == b ) end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  31. 31. Introduction Metaprogramming DSL implementation Ruby and Metaprogramming Summary DSLs in Ruby : my own DSL f i r s t 1 , f i r s t 2 , l a s t = ’ p e t e r ’ , ’ glenn ’ , / Av / banks = query do from : a => Account s e l e c t a . bank . name where ( ( a . owner . f i r s t n a m e == f i r s t 1 ) | ( a . owner . f i r s t n a m e == f i r s t 2 ) ) & ( a . owner . lastname =~ l a s t ) end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  32. 32. Introduction Metaprogramming DSL implementation Ruby and Metaprogramming Summary DSLs in Ruby : my own DSL f i r s t 1 , f i r s t 2 , l a s t = ’ p e t e r ’ , ’ glenn ’ , / Av / banks = query do from : a => Account c = a . owner s e l e c t a . bank . name where ( ( c . f i r s t n a m e == f i r s t 1 ) | ( c . f i r s t n a m e == f i r s t 2 ) ) & ( c . lastname =~ l a s t ) end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  33. 33. Introduction Metaprogramming DSL implementation Ruby and Metaprogramming Summary DSLs in Ruby A Ruby DSL is just plain Ruby Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  34. 34. Introduction Metaprogramming DSL implementation Ruby and Metaprogramming Summary DSLs in Ruby easy to build O OOO OOO OOO O' A Ruby DSL is just plain Ruby Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  35. 35. Introduction Metaprogramming DSL implementation Ruby and Metaprogramming Summary DSLs in Ruby easy to build familiar syntax O OOO n nnn OOO nnn OOO nn wnnn O' A Ruby DSL is just plain Ruby Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  36. 36. Introduction Metaprogramming DSL implementation Ruby and Metaprogramming Summary DSLs in Ruby easy to build familiar syntax O OOO n nnn OOO nnn OOO nn wnnn O' A Ruby DSL is just plain O Ruby abstraction Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  37. 37. Introduction Metaprogramming DSL implementation Ruby and Metaprogramming Summary What I’ll Teach You f i r s t 1 , f i r s t 2 , l a s t = ’ p e t e r ’ , ’ glenn ’ , / Av / banks = query do from : c => Customer , : b => Bank , : a => Account s e l e c t b . name where ( ( c . f i r s t n a m e == f i r s t 1 ) | ( c . f i r s t n a m e == f i r s t 2 ) ) & ( c . lastname =~ l a s t ) & ( a . owner == c ) & ( a . bank == b ) end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  38. 38. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Outline Introduction 1 Metaprogramming Ruby and Metaprogramming DSL implementation 2 Changing self Missing constants Missing methods Implementing custom operators Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  39. 39. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators What is self? self is the current object Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  40. 40. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators What is self? instance variables OO OOO OOO OOO ' self is the current object Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  41. 41. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators What is self? instance dotless variables OO methods n OOO n nnn OOO nnn OOO vnnn ' self is the current object Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  42. 42. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators What is self? instance dotless variables OO methods n OOO n nnn OOO nnn OOO vnnn ' self is the current object 8 qqq q qqq qqq qq class variables Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  43. 43. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators What is self? instance dotless variables OO methods n OOO n nnn OOO nnn OOO vnnn ' self is the current object 8 gOOO qqq O OOO q qqq OOO qqq O qq changed by class method calls, variables class defs Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  44. 44. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators What is self? banks = query do ... end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  45. 45. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators What is self? banks = s e l f . query do ... end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  46. 46. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators What is self? # Top l e v e l p self # => main p s e l f . class # => O b j e c t Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  47. 47. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators What is self? banks = s e l f . query do ... end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  48. 48. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators The Kernel module Kernel Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  49. 49. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators The Kernel module puts O OOO OOO OOO O' Kernel Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  50. 50. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators The Kernel module puts O raise OOO qqq OOO qqq OOO qq xqqq O' Kernel Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  51. 51. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators The Kernel module puts O raise OOO qqq OOO qqq OOO qq xqqq O' Kernel oo7 ooo ooo ooo require Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  52. 52. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators The Kernel module puts O raise OOO qqq OOO qqq OOO qq xqqq O' KernelMM fMMM oo7 ooo M ooo MMM ooo MM require eval Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  53. 53. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators The query method module K e r n e l def query yield # C a l l the block end end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  54. 54. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Changing self banks = query do from : c => Customer , : b => Bank , : a => Account ... end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  55. 55. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Changing self banks = query do s e l f . from : c => Customer , ... ... end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  56. 56. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Changing self banks = query do p s e l f # => main end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  57. 57. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Changing self banks = query do s e l f . from : c => Customer , ... ... end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  58. 58. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Changing self Sometimes we want to change self Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  59. 59. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Changing self class Query end module K e r n e l def query (& b l k ) Query . new . i n s t a n c e _ e v a l (& b l k ) end end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  60. 60. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Changing self banks = query do p s e l f # => #<Query : 0 xb7cc4adc > end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  61. 61. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Changing self instance_eval changes self for the duration of a block Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  62. 62. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Changing self class Query def i n i t i a l i z e @from = { } end def from (map) @from = map end end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  63. 63. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Changing self banks = query do from : c => Customer , : b => Bank , : a => Account p s e l f # => #<Query : 0 xb7cc4adc # @from = { : b=>Bank , : a=>Account , : c=>Customer } > end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  64. 64. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Outline Introduction 1 Metaprogramming Ruby and Metaprogramming DSL implementation 2 Changing self Missing constants Missing methods Implementing custom operators Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  65. 65. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Lazy class loading Rails can do lazy class loading Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  66. 66. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Lazy class loading test.rb # r e q u i r e ’ brug ’ BRUG. new ( Time . now ) brug.rb class BRUG def i n i t i a l i z e ( t i m e ) @time = t i m e end end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  67. 67. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Constant lookup BRUG.new Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  68. 68. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Constant lookup BRUG.new n = Module.nesting + [Object] Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  69. 69. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Constant lookup BRUG.new n = Module.nesting + [Object] find BRUG in n Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  70. 70. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Constant lookup BRUG.new n = Module.nesting + [Object] find BRUG in n u u uu uu u founduuu uu uu uu uu zuu return BRUG Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  71. 71. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Constant lookup BRUG.new n = Module.nesting + [Object] u KK find BRUGKin n u KK uu KK uu KK u founduuu KK found not KK uu KK uu KK uu KK uu KK zuu % n [0]. const_missing(:BRUG) return BRUG Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  72. 72. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Module.nesting class A module B def m Module . n e s t i n g # = [ A : : B , A ] end Module . n e s t i n g # = [ A : : B , A ] end end Module . n e s t i n g # = [ ] def A .m Module . n e s t i n g # = [ ] end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  73. 73. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Lazy class loading banks = query do from : c = Customer , : b = Bank , : a = Account p Module . n e s t i n g + [ O b j e c t ] # = [ O b j e c t ] ... end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  74. 74. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Lazy loading def O b j e c t . c o n s t _ m i s s i n g ( c i d ) f i l e = f i n d _ f i l e ( cid ) require f i l e const_get ( cid ) end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  75. 75. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Lazy class loading def O b j e c t . c o n s t _ m i s s i n g ( c i d ) f i l e = f i n d _ f i l e ( cid ) require f i l e i f const_defined? cid const_get ( cid ) else # c a l l old const_missing end end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  76. 76. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Lazy class loading def O b j e c t . c o n s t _ m i s s i n g ( c i d ) f i l e = f i n d _ f i l e ( cid ) require f i l e i f const_defined? cid const_get ( cid ) else # Class Module super end end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  77. 77. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Lazy class loading Lazy class loading is freakingly easy Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  78. 78. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Outline Introduction 1 Metaprogramming Ruby and Metaprogramming DSL implementation 2 Changing self Missing constants Missing methods Implementing custom operators Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  79. 79. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Handling b.name banks = query do ... s e l e c t b . name ... end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  80. 80. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Handling b.name banks = query do ... s e l e c t s e l f . b . name ... end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  81. 81. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Handling b.name class Query def b ... end end banks = query do ... s e l e c t s e l f . b . name ... end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  82. 82. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Handling b.name Can we avoid mass method definition ? Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  83. 83. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Missing methods self .b.name Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  84. 84. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Missing methods self .b.name ww ww ww b foundwww w ww ww w ww {ww self .b.name Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  85. 85. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Missing methods self .b.name J JJ ww JJ ww JJ ww JJ b foundwww J bJnot found w JJ ww JJ ww JJ w JJ ww J$ {ww self .method_missing(:b) self .b.name Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  86. 86. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Implementing Query#method_missing banks = query do ... p s e l f # = #Query : 0 xb7cf5dd4 s e l e c t s e l f . b . name ... end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  87. 87. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Implementing Query#method_missing class Query def method_missing ( mid , ∗ args ) i f args . l e n g t h == 0 @from [m] V a r i a b l e E x p r e s s i o n . new (m) else super end end end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  88. 88. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Implementing Query#method_missing class V a r i a b l e E x p r e s s i o n 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 peter@xaop.com Metaprogramming in Ruby
  89. 89. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Alternative implementation class Query a l i a s old_mm method_missing def method_missing (m, ∗ args ) i f args . l e n g t h == 0 @from [m] V a r i a b l e E x p r e s s i o n . new (m) else old_mm (m, ∗ args ) end end end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  90. 90. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Implementing Expression#method_missing banks = query do ... # select b s e l e c t b . name ... end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  91. 91. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Implementing Expression#method_missing class Expression def method_missing (m, ∗ args ) i f args . l e n g t h == 0 F i e l d E x p r e s s i o n . new ( s e l f , m) else super end end end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  92. 92. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Implementing Expression#method_missing class F i e l d E x p r e s s i o n Expression def i n i t i a l i z e ( expression , f i e l d ) @expression , @ f i e l d = expression , f i e l d end end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  93. 93. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Summary YES, we can avoid mass method definition Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  94. 94. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Outline Introduction 1 Metaprogramming Ruby and Metaprogramming DSL implementation 2 Changing self Missing constants Missing methods Implementing custom operators Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  95. 95. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Oerator overloading banks = query do ... where ( ( c . f i r s t n a m e == f i r s t 1 ) | ( c . f i r s t n a m e == f i r s t 2 ) ) ( c . lastname =~ l a s t ) ( a . owner == c ) ( a . bank == b ) end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  96. 96. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Operator overloading Operators are just methods Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  97. 97. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Operator overloading banks = query do ... where ( ( c . f i r s t n a m e . = = ( f i r s t 1 ) . | ( c . firstname .==( f i r s t 2 ) ) . ( c . lastname . = ~ ( l a s t ) . ( a . owner == c ) . ( a . bank . = = ( b ) ) end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  98. 98. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Implementing operator overloading class Expression def ==( o t h e r ) BinaryOpExpression . new ( s e l f , o t h e r , ’= ’ ) end def ( o t h e r ) BinaryOpExpression . new ( s e l f , o t h e r , ’AND ’ ) end ... end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  99. 99. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing 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 peter@xaop.com Metaprogramming in Ruby
  100. 100. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Limitations operator overloading , ||, ! are NOT methods Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  101. 101. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Summary but ... Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  102. 102. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Limitations operator overloading Operator overloading is child’s play Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  103. 103. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Wrapping up the example banks = query do ... where . . . end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  104. 104. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Wrapping up the example class Query def where ( cond ) @where = cond end end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  105. 105. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Wrapping up the example class Query def t o _ s q l quot;SELECT # { r e t u r n _ l i s t } quot; quot;FROM # { t a b l e _ l i s t } quot; quot;WHERE # { c o n d i t i o n _ e x p r } quot; end end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  106. 106. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Wrapping up the example class Query def t a b l e _ l i s t @from . map { | v , t | quot; # { t } AS # { v } quot; } . j o i n ( quot; , quot; ) end def r e t u r n _ l i s t @select . map { | r | r . t o _ s q l } . j o i n ( quot; , quot; ) end def c o n d i t i o n _ e x p r @where . t o _ s q l end end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  107. 107. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Wrapping up the example f i r s t 1 , f i r s t 2 , l a s t = ’ p e t e r ’ , ’ glenn ’ , / Av / banks = query do from : c = Customer , : b = Bank , : a = Account s e l e c t b . name where ( ( c . f i r s t n a m e == f i r s t 1 ) | ( c . f i r s t n a m e == f i r s t 2 ) ) ( c . lastname =~ l a s t ) ( a . owner == c ) ( a . bank == b ) end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  108. 108. Introduction DSL implementation Summary Summary Ruby has very natural metaprogramming facilities Ruby allows building DSLs in pure Ruby Metaporgramming made easy Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  109. 109. Introduction DSL implementation Summary Summary Ruby has very natural metaprogramming facilities Ruby allows building DSLs in pure Ruby Metaporgramming made easy Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  110. 110. Introduction DSL implementation Summary Summary Ruby has very natural metaprogramming facilities Ruby allows building DSLs in pure Ruby Metaporgramming made easy Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  111. 111. Introduction DSL implementation Summary Further reading why’s (poignant) guide to Ruby http://poignantguide.net/ruby/ http://poignantguide.net/ruby/chapter-6.html Ruby for Rails http://www.manning.com/black/ Programming Ruby http://www.rubycentral.com/pickaxe/ http://www.pragmaticprogrammer.com/title/ruby/ Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  112. 112. Introduction DSL implementation Summary Further reading why’s (poignant) guide to Ruby http://poignantguide.net/ruby/ http://poignantguide.net/ruby/chapter-6.html Ruby for Rails http://www.manning.com/black/ Programming Ruby http://www.rubycentral.com/pickaxe/ http://www.pragmaticprogrammer.com/title/ruby/ Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  113. 113. Introduction DSL implementation Summary Further reading why’s (poignant) guide to Ruby http://poignantguide.net/ruby/ http://poignantguide.net/ruby/chapter-6.html Ruby for Rails http://www.manning.com/black/ Programming Ruby http://www.rubycentral.com/pickaxe/ http://www.pragmaticprogrammer.com/title/ruby/ Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  114. 114. Introduction DSL implementation Summary REAL Summary Ruby rocks!!! Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby

×