Neat trick: delaying variable evaluation in Ruby meta-code

Working on rb-skypemac 0.2.0, I found myself in the position of either implementing 40 getter/setter pairs by hand or writing some meta code. I always prefer to write meta code. If you don’t, seek treatment – or else you will soon find yourself in treatment of the straight jacket variety.

Anyhow, as I’m writing this meta code, I realized that I needed to delay the evaluation of a variable inside a String, i.e., delaying the evaluation of #{stuff} within “This is a load of #{stuff}”. Why? Because I didn’t have the variable yet! The variable is an instance variable and my meta code generating method is at the class level. So I began to stress. And then I figured, what the hell; I’ll just escape the ‘#’ because that would just make sense.

You know what? It just worked.

Matz did one fine job designing several portions of this language!

Example below:

  class User
    def User.skype_attr_reader(*attr_sym)
      attr_sym.each do |a|
        module_eval %{def #{a.to_s}
          # The line below is the REALLY cool part
          r = Skype.send_ :command => "get user \\#{@handle} #{a.to_s}"
          r.sub(/^.*#{a.to_s.upcase} /, "")
        end}
      end
    end

    skype_attr_reader :fullname, :birthday, :sex, :language, :country, :province

Posted by evan on Tuesday, April 24, 2007

blog comments powered by Disqus