Skip to content
First Step on Ruby Metaprogramming.
Ruby
Find file
Pull request Compare This branch is 8 commits behind ashbb:master.
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.
html
imgs
md
public
src
tools
README.md
config.ru
first_step_on_ruby_metaprogramming.rb

README.md

First Step on Ruby Metaprogramming




First Week

Let's start learning Ruby Metaprogramming!


Study 0

1st, review the built-in, read-only variable self. Read the following articles:

2nd, review singleton class. Read the following article:

3rd, review the scope of variables. Read the following article:


Study 1

To learn about the following methods read The Book of Ruby, Chapter 20: Dynamic Programming.

  • eval
  • instance_eval
  • class_eval (aka: module_eval)
  • class_variable_set
  • class_variable_get
  • class_variables (Try it out: instance_variables)
  • instance_variable_set (Try it out: instance_variable_get)
  • define_method
  • const_set
  • const_get (Try it out: constants)
  • Class.new (Try it out: Struct.new)
  • binding (Try it out: lambda)
  • send (Try it out: method)
  • remove_method
  • undef_method
  • method_missing


Study 2

Read _why's hacking, Seeing Metaclasses Clearly to learn about the following singleton class (metaclass)

  • class << self; self; end


Study 3

Read Marc-Andre Cournoyer's blog, Extending your include knowledge of Ruby to learn about the following methods to read Marc-Andre Cournoyer's blog, Extending your include knowledge of Ruby. Also read Ruby-Doc Core API: Module#included and Module#extended

  • include
  • extend
  • included
  • extended


Before Exercises

Watch the following presentation, the Scotland on Rails conference 2009, by Dave Thomas.

The Ruby Object Model


Exercises

Try to do the following exercises. Let's discuss all these exercises in the relevant thread in the First Week Forum.

  • Exercise 1: Get the values from outside the class.
  • Exercise 2: Add your code to display 'I like metaprogramming!'
  • Exercise 3: Show lots of ways to define singleton method.
  • Exercise 4: Glance into Ruby inside with binding method.
  • Exercise 5: Define the class without class and def.


Watch the video

Watch the Dave Thomas's presentation about Metaprogramming.

MetaProgramming - Extending Ruby for Fun and Profit

Understand these concepts:

  • Classes are open
  • Definitions are active
  • All method calls have a receiver
  • Classes are objects


Cheat Sheet

  • Cheat Sheet: a list of Ruby metaprogramming techniques




Second Week

Well, let's practice how to write a tiny app with Ruby Metaprogramming techniques.

Note: If you have an idea in your mind. Feel free, please show us and try to do that.


Assignment 1

Define class Dog.


Step 1

There are three dogs named Lassie, Fido and Stimpy.
Look at dog_game.rb. Expected output is the following:

"Lassie is dancing"
"Lassie is a smelly doggy!"
"Lassie finds this hilarious!"

"Fido don't understand dance"
"Fido is a smelly doggy!"
"Fido don't understand laugh"

"Stimpy is dancing"
"Stimpy don't understand poo"
"Stimpy don't understand laugh"

Create dog.rb stored the class Dog.

Hints:

  • class Dog has three methods: initialize, can, method_missing
  • may be useful to define the static data like this: MSGS = {:dance => 'is dancing', :poo => 'is a smelly doggy!', :laugh => 'finds this hilarious!'}


Step 2

Challenge: Improve a little bit.

Look at dog_game.rb. Expected output is the following:

"Lassie is dancing"
"Lassie is a smelly doggy!"
"Lassie finds this hilarious!"

"Fido don't understand dance"
"Fido is smelly."
"Fido don't understand laugh"

"Stimpy is dancing"
"Stimpy don't understand poo"
"Stimpy don't understand laugh"
"Stimpy cried AHHHH"

Let's improve dog.rb.

Hints:

  • use can method with block like this: stimpy.can(:cry){"#{name} cried AHHHH"}
  • define the name method



Assignment 2

Follow these steps to create a tiny XML generator: xml.rb

We can use it like this:

  • Look at sample_html.rb
  • Need to write XML class with xml_generate() method.
  • Line 9-22 is our tiny DSL code to create the output (xml format text). It'll be stored to sample_twitters.html file at the last line.
  • Line 4-6 is the input data, just a sample for this practice.
  • Look at the output: sample_twitters.html and a screenshot.


Step 1

Let's start!
Create two files: sample_html.rb and xml.rb

sample_html.rb has the following features.

  • create a XML object
  • call xml_generate() method
  • at first, the input is only one line: content "Let's start!"
  • store the output (created xml)


xml.rb has the following three instance methods.

  • initialize
  • content
  • xml_generate


Hint: instance_eval


Look at the input and output for Step 1.


Step 2

Improve to accept the following inputs.

html do
  body do
    content "Let's start!"
  end
end


Hint: method_missing


Look at the input and output for Step 2.


Step 3

Improve to accept the following inputs.

html do
  body do
    content "Let's start!"
    form :action => '/page', :method => 'post' do
      input :type => 'text', :name => 'str', :maxlength => 3, :size => 3
      input :type => 'submit', :value => 'page'
    end
  end
end


Hint: hash


Look at the input and output for Step 3.


Step 4

Improve to accept the following inputs.
Use this pic as a avatar.

html do
  body do
    twitters.each do |tw|
      img :src => tw.avatar, :alt => tw.name, :width => 25, :height => 25
      content [" : " , tw.text]
      br
      br
    end
    form :action => '/page', :method => 'post' do
      input :type => 'text', :name => 'str', :maxlength => 3, :size => 3
      input :type => 'submit', :value => 'page'
    end
  end
end


Hint: no need to use any more metaprogramming tech.


Look at the input and output for Step 4.


Step 5

We want to replace XML.new.xml_generate to XML.generate.


Hint: define class method


Let's discuss your code in the relevant thread in the Second Week Forum.


For More Study

Try to hack the Sample Apps on Ruby Metaprogramming Study Note


Interesting Articles


Note

There are a few more useful hook methods for metaprogramming.

  • inherited
  • method_added

I'd like to exercise them at the next batch. ;-)




2009.7.6 Satoshi Asakawa

Something went wrong with that request. Please try again.