Many Rubist’s first explanation of metaprogramming is by why the lucky stiff (_why)’s Why’s (Poignant) Guide to Ruby, chapter 6, section 3.
You go on a dragon-hunting, adventure game using sexy Ruby syntax (a domain-specific language/DSL for adventure games?). Here is some sample syntax for defining a monster class:
class Dragon < Creature
life 1340 # tough scales
strength 451 # bristling veins
charisma 1020 # toothy smile
weapon 939 # fire breath
end
The life, strength, charisma and weapon class methods are generated by a traits class method called against the Creature class (read the chapter).
class Creature
traits :life, :strength, :charisma, :weapon
end
Read this chapter section many times and admire the beauty of the idea (and amuse yourself with his writing style!).
But there is one small improvement that could be made: currently, after setting the trait methods (e.g. life 1340 sets the life trait to 1340), you cannot access the class's trait values directly via their original trait method. That is, you cannot call Dragon.life to retrieve the value 1340.
This is due to a limitation of the define_method method being used. The relevant code from _why's book is:
def self.traits( *arr )
# 2. Add a new class method to for each trait.
arr.each do |a|
metaclass.instance_eval do
define_method( a ) do |val|
@traits ||= {}
@traits[a] = val
end
end
end
The method creator define_method uses a block to define the generated method body. The parameters for the block (val in the example above) become the arguments of the method once its been added to the class. That is, if we call traits :life on our Creature class, then a class method will be generated that requires one argument - the value of the trait. That is, it will generate the following method:
class Creature
def life(val)
@traits ||= {}
@traits[:life] = val
end
end
Now, back to the problem. How do we support the syntax Dragon.life? To achieve this, the generated method would need to look like:
class Creature
def life(val = nil)
@traits ||= {}
return @traits[:life] if not val
@traits[:life] = val
end
end
That is, we need a default value for our method argument. But... blocks don't allow parameters to have default values. We cannot do the following:
define_method( a ) do |val = nil|
@traits ||= {}
return @traits[a] if not val
@traits[a] = val
end
A pity, yes.
So, we need to generate our methods differently. The solution is as follows:
metaclass.class_eval <<-EOS
def #{a}(val=nil)
@traits ||= {}
return @traits[:#{a}] if not val
@traits[:#{a}] = val
end
EOS
The eval methods allow a string to be passed to them. So, we shall pass it a string that defines a new method the old fashioned way: using the def method constructor. Thus it allows us to have default values for our arguments.
QED.
ALTERNATIVE from Chris @ Errtheblog.com
Use the splat! (*) to allow zero or more arguments. Pluck the first one off to represent the incoming argument or nil.
def self.traits( *arr )
arr.each do |a|
metaclass.instance_eval do
define_method( a ) do |*val|
val = val.first
@traits ||= {}
return @traits[a] if not val
@traits[a] = val
end
end
end
end
There are unanswered questions about its support for 2+ arguments (where we only need support for 0 or 1) that shall remain unanswered for the sake of this simple hack. But feel free to start throwing exceptions around if your users need protection from themselves.
Rails’ active_support library adds some wonderful functions into standard Ruby classes. Some we all use day-in-day out are attr_accessor and its class-level equivalent, cattr_accessor.
But cattr_accessor doesn’t work the way you (read, “me”) thought at first glance when you use subclasses. I thought if I declared a class accessor in the superclass, then I would have independent class attributes for all my subclasses. Apparently not…
>> class Parent; cattr_accessor :val; end
=> [:val]
>> class Child1 < Parent; end
=> nil
>> class Child2 < Parent; end
=> nil
>> Child1.val = 4
=> 4
>> Child2.val
=> 4
>> Child2.val = 5
=> 5
>> Child1.val
=> 5
Child1.val and Child2.val seem to be the same value. Not very independent at all. Internally, the classes share a common class attribute. This is useful in certain circumstances, but not what I was looking for.
Instead, I found class_inheritable_accessor.
>> class Parent; class_inheritable_accessor :val; end
=> [:val]
>> class Child1 < Parent; end
=> nil
>> class Child2 < Parent; end
=> nil
>> Child1.val = 4
=> 4
>> Child2.val = 4
=> 4
>> Child2.val = 5
=> 5
>> Child1.val
=> 4
Lovely. Each subclass will have an independent value once you’ve assigned it a value explicitly, else it will pick up the value from its superclass.
UPDATE: class_inheritable_accessor and co. actually clone the superclass’s inherited attributes, rather than just referencing them.
I’m not promising there ever will be a Dr Nic’s Online Civilizations game, but it has seemed like a good idea for a few weeks, and today I went from ASCII map through to beautiful CSS rendering of the map.
6am ASCII to HTML mapping |
8am Base tiles |
6pm Correct edges |
9pm Convert table to div structure |
 |
 |
 |
 |
I miss home.

This was a technically interesting process. The images used are actually all on the one base tile sheet
[1], and each panel of the map is allocated a separate CSS class relating to the specific tile required.
So for example, to show the base grasslands tile, you’d need some CSS like:
.tiles {height: 30px; width: 30px; background: url(tiles.png) top left no-repeat; ...}
.grasslands {background-position: 0px -30px;}
For a desert tile, with some grasslands to the left, you might use:
.desert-left {background-position: -60px -60px;}
This really gives a nice tiling effect without you needing to do any fancy image manipulations or the user loading up lots of small images. You just assign the appropriate CSS class to the panel (a DIV or TD, for example). Want to change a tile? Change the class (e.g. using Prototype/jQuery libraries)
Yes, this solution requires lots of individual CSS class definitions; but you’re clever – you’ll generate them won’t you
Reader assistance required
The one technical trick that I don’t have a solution for at the moment is a Google Maps-like interface for scrolling map around. I’d love to hear from anyone with some bright thoughts on how they implement that (I don’t want to have to try to read their compact Javascript code).
Any thoughts?
[1] The source images came from the FreeCiv GPL game
[Original article published on DevLounge - please post comments there]
When you unpack your shiny new version of Rails and generate your first Ajax link, you are using the Prototype library. It’s beautiful to use. It adds many Rails-like constructs into the Javajscript language, e.g. the each method to iterate a closure over an array. Sexy stuff.
But the following effect isn’t done using Prototype:
It was done in a few lines of Javascript using the jQuery library [1].
$(".tick").hover(function() {
$(this).removeClass("tick-off").addClass("tick-on").announceButton(this)
}, function() {
$(this).removeClass("tick-on").addClass("tick-off");
});
Prototype provides a comprehensive library of base classes, such as Element and Hash, where as jQuery is fundamentally different. It provides just one entity – the jQuery object. This is created using the familiar $ function and represents a collection of DOM nodes, rather than just one.
The jQuery object is then extended and extended and extended with all the functionality you need – scriptaculous-like effects, Ajax calls, prototype-like manipulations, etc. JQuery plugins
Yehuda Katz – author of autoDB – the dynamic admin console for Rails apps – has his feet deep in jQuery land as well. He manages the Visual JQuery documentation, and recently wrote an article comparing the philosophies of Prototype and JQuery, to help people understand how they are different.
The core problem for Rails developers who might like to try out jQuery is that it eventually conflicts with the prototype library when you start to use Rail’s “in-built” helpers for prototype.
But perhaps you do not need to use these helpers, as an increasing number of jQuery plugins start to provide more and more elegant client-side functionality. For example, an InPlaceEditor extension, and many others.
Want something truly pretty developed using jQuery – how about the planets revolving around the sun?
Work is also underway to integrate jQuery into Rails, including its own set of helpers, code named JQuails.
Many Rails developers might not be familiar with the abilities of alternative Javascript libraries as they get prototype/scriptaculous embedded for free. Yet it would be wise for all developers to be aware and competent in multiple frameworks, so that the best tools for each job can be selected. There is certainly some momentum behind jQuery in the wider development community. To Rails developers I say, Keep a Look Out!
[1] The Hover Demo Script was written as pure Javascript to make it easy to download. Firstly it disables the static image (for RSS feed and non-JS environments), and then creates the DIVs for the effect. The hover effect is then setup by applying the hover function to all elements of the class tick. The two functions we pass it perform the CSS class manipulation that gives the effect. Note the use of chain calls that make the syntax so attractive.
Note also that we’ve added a custom function to the jQuery object – announceButton. It assumes that only one button is active at a time, uses this[0] to determine which one it is. The function then returns the jQuery object (stored as this) to allow the standard method chaining to continue.
Dr Nic’s Magic Models are magical, that goes without saying. But are they efficient at being magical? Do you get the same speed in your application as if you explicitly defined your classes and your associations will your application execute faster?
Yes. The cost of accessing a Magic Model and a normal ActiveRecord is exactly the same – once the Magic Model has been initially generated. Its just a normal ActiveRecord like all your other ActiveRecords: they are loaded into memory when you first ask for them. Normal ActiveRecords are loaded into memory from your /app/models/.rb file; Magic Models are generated classes. The Magic Models would in fact be quicker to load as there is no file access required.
The cost of accessing Automatic Associations versus normal Active Record associations is also exactly the same. To understand the inner workings of associations, see err.the_blog’s latest article.
The point to take away from the discussion is that associations are a generated method on your class. Once you’ve generated it once (at the time you call has_many for example), you have it permanently. So there is only a small, one-time cost for the Automatic Associations – to see which association to generate for the incoming method call. But once you’ve generated the association, its yours permanently.