ruby metaprogramming 08
DESCRIPTION
An introductory presentation about Ruby metaprogramming presented at CodeMash '08TRANSCRIPT
RailsA Peek under the covers
Brian Sam-Bodden
Rails
A framework...
for building database-backed web applications
that at first wow us with speed
Rails can be seen as a collection of...
mini-languages
for implementing MVC
on the web
then came the headlines...
and we all wondered...
what am I doing wrong?
too much
the answer
and we reacted
the way we knew better
...with frameworks
Lessons of Rails
Integrated
Familiar idioms on every tier
Seamless front to back stack
Avoiding manually defining or gluing the tiers
CoC
“Flexibility is overrated, Constraints are liberating”
Convention Over Configuration
DRYDo it once, do it right and do it in the right place
Tight feedback loop
We want the world and we want it NOW!
Instant Change
Getting advanced behavior with very little code
Without sacrificing readability
Terse Expressiveness
Did the clones catch up?
Yes and Not quite, Sort of
✓CoC
✓ Instant Change๏Terse Expressiveness
✓DRY
✓Integrated
What’s Missing?
Rubyis...
✓Object-Oriented
✓Reflective ✓Dynamic
✓ Interpreted
✓General Purpose
✓ Multi-paradigm
✓ Garbage-collected
✓Elegant
Without Ruby there would be no Rails
Ruby’s Dynamism is the key ingredient to the Rails framework
Open Classes
Say we have an Array like:
[1,2,3,4,5]and we want to sum of all of its elements
Let’s try something like:
[1,2,3,4,5].sum
Doh! Doesn’t work in Ruby … yet!
Ruby classes are open
We can teach the Array class a new behavior
Let’s try again!
Load the file containing the enhancements
Since Ruby classes are open...
You can statically enhance ANY class
Code as Data
When code can be manipulated as dataa whole world of possibilities opens
In Ruby you can evaluate the contents of a string
Code that spits out code
Ruby provides the eval family of methods for runtime execution of code stored in strings
eval will evaluate any string
instance_eval can evaluate a string or a code block
in the context of the receiver
class_eval can evaluate a string or a code block
in the context of the class or module it is called on
Meta-programming
...is about programs that write programs
Meta-programming
...it’s a superb tool for building frameworks
...it’s the key ingredient for building domain-specific languages
Ruby is a great language for meta-programming because
...is dynamic and reflexive
...open and malleable
...clean unencumbered syntax
...code is data, data is code
...programming event model
...uses the Ruby meta-programming techniques to accomplish most of its “magic”
...uses meta-programming to bring the language closer to the problem at hand
Rails
...is a domain-specific language for building web applications
Singleton Class
All objects are open to modification
You can change a particular instance of a class
Ruby uses a proxy class known as the singleton class
Meta-class: The singleton for Class objects
With access to a class object’s meta-class we can then use Ruby meta-programming techniques to
enhance the class
Rails relies heavily on Ruby’s ability to dynamically enhance a class
The previous example could have also been accomplished using the define_method
Accessing the singleton meta-class explicitly
Inheritance the Ruby Way
Rails uses this technique in ActiveRecord
Ruby Meta-programming techniques can be used to write DSLs that use class methods to enhance
subclasses
Using the meta-class (singleton class) of the subclasses
Let’s create a module with a “Base” class
Methods get added to our classes with simple declarationsCan you say DSL!
Rails uses this technique in ActiveRecord
Now our class has a new set of class methods
AOP the Ruby Way
With alias_method you can wrap an existing method
Meta-Programming Events
Included Hook
Ruby has a rich event model associated with static and dynamic changes of the code
Method Missing
Ruby provides several hook methods that can be used to created custom behaviors
method_missing
method_added
method_removed
Let’s implement the greeter example using method_missing
There is more to Ruby than Rails!
Building a Framework? Give Ruby a try!
Build the language up towards the problem
Meta-programming is no longer just for the Lisp folks
The future? Powerful Java APIs exposed with Ruby DSLs