RSS: Articles| Comments| Trackbacks
 

Squeaker Squeakerson

Posted by haakon, Thu, 19 Oct 2006 17:26:42 GMT

A random post for the fam – here is Trygve making some noise as he plays>

Squeaker Squeakerson

Autumn Respite

Posted by Jenny, Mon, 16 Oct 2006 09:24:33 GMT

I thought that after the last couple techy posts (informative and enlightening as they are) I would change the pace a touch.

I am continually amazed at how quickly time passes. I look at our son who is coming up for 12 weeks on Thursday and think, when did he get to be such a little person? Last time I checked it was the beginning of August and now in the blink of an eye we are in the thick of October. I’m usually heard complaining about the weather in Edinburgh, but as of late, it has been absolutely beautiful and I wanted to put it on record that I am enjoying this Autumn fully.

Yesterday afternoon I went for a walk with a new friend Jennie and her 13 week old son Louis. We meandered through the cobbled streets, enjoying the crisp air and the lovely colours. We walked towards the “Hermitage” which is a large ‘park’ just south of our flat with fields, a large hill, pond, creek, and woodland as well. I love that in just 20 minutes walking I can go from the upbeat pace of the city to tranquil countryside. We walked through a field and sat on a bench overlooking it all as the sun was beginning to set. The trees were showing off their full colours, the sky was a lovely hue of pink, and both our sons were peacefully sleeping—a virtual moment of heaven. It was a lovely break in the midst of what can feel like a busy and hectic life filled with feeding, nappy changing, and trying to get chores done around the house. We paused for several blissful moments and took it all in before walking back to home, city, and the clambering needs of our wee little men. A short Autumn respite indeed, but it made for a restorative Sunday evening.

~Jenny

Final methods in ruby (prevent method override)

Posted by haakon, Fri, 06 Oct 2006 14:10:00 GMT

In a reversal of fortune, I recently found myself wishing Ruby was more like Java. Java has the ideas of abstract base classes and final methods (methods which should not be overridden in child classes). Such ideas don’t really exist in Ruby.

My problem was this. I had a base class Cronjob which represented some job which was going to run under cron. This class managed stuff like setting up logging, db connections, etc. I then wanted other jobs to be able to extend Cronjob and take advantage of the base class:

class Cronjob
  def initialize
    # do useful stuff here, setting up db connections, logging, etc.
  end

  def run   # method which no child class should override
    start = Time.now
    puts "starting at #{start}"
    run_job    # method which child class should override
    stop = Time.now
    puts "finished at #{stop}, took #{stop-start} seconds"
  end
end
This then allowed me to write a child class that did the real work:
class MyJob < Cronjob
  def run_job
    # real work goes here
  end
end 
And then call:
job = MyJob.new
job.run

All well and good. If people use the base class correctly, they get some nice bits of functionality. However, I eventually noticed that someone had written this class:

class TheirJob < Cronjob
  def run
    # real work goes here
  end
end 
This is bad! The author thinks they are taking full advantage of the base class, but they are not. In reality they are overriding the run method, and Ruby does not complain a bit. This is where if I were in Java I could use the final keyword to say that a method should not be overriden by any child classes. What I wanted was to be able to write:
class Cronjob
  final :run

  def run
  end
end
So, how can we make this work? Here is my solution that does the job.
class Object
  @@final_methods = {}

  class < < self
    def prevent_override?(method_name)
      @@final_methods.each do |class_name, final_methods|
        ancestors = self.ancestors
        ancestors.shift # remove myself from the list
        if ancestors.include?(class_name) and
           final_methods.include?(method_name)
          raise "Child class '#{self}' should not override parent class method '#{class_name}.#{method_name}'."
        end
      end
    end

    def method_added(method_name)
      prevent_override?(method_name)
    end

    def final(*names)
      @@final_methods[self] = names
    end

  end
end 
Now if someone tries to override the method in a child class they get an exception:
in `prevent_override?': Child class 'TheirJob' should not
override parent class method 'Cronjob.run'.(RuntimeError)

How does it work? The magic is possible because Ruby has a method called method_added. This gets called when a method is added to a class. So, when a source code file is being processed, if a method is defined with “def foo”, after the method has been added to the class this method_added method gets fired with “foo” as the argument. We can then implement the method with our desired behavior. In my case, I just wanted to blow up with an exception which is easy enough to do.

Ruby also has a method to get an object’s “ancestors”.
>> true.class.ancestors
=> [TrueClass, Object, Kernel]
>> [].class.ancestors
=> [Array, Enumerable, Object, Kernel]

So, the logic becomes simple. The final method just stores a hash of class => [methods which you cannot override]. Then, on method_added we do a check to see if the method being added is in this hash, and Bob’s your uncle!

So, while it was mildly surprising to find Ruby missing a language feature that I wanted, the language is powerful enough that you can “add to” the language! I’m also half expecting people to weigh in with suggestions of a better way to do this. I would be pleased to hear better variations. This solution definitely doesn’t make it impossible to override the method in a child class; a determined person could get around it. But it does solve my problem of someone inadvertently overriding the method.

Update: Now available via gems, thanks to Dr. Nic’s newgem magic:

gem install finalizer