Hi, I've been trying out Prototype's framework for Class creation.
I've read the code and made an implementation of the ruby feature
method_missing. Are there any other attempts to achieve this. Is it
needed? Mine is probably quite buggy. =)

Put this code in a html-page that includes prototype to try out my
small example. It monkey patches Class.create and
Class.Methods.addMethods. The $super keyword doesn't work, so it need
to be rewritten. It will only work for code that is executed within
the context of a class, so keep it pure OO!

  var Class = {
    create: function() {
      var parent = null, properties = $A(arguments);
      if (Object.isFunction(properties[0]))
        parent = properties.shift();

      function klass() {
        this.initialize.apply(this, arguments);
      }

      document.writeln("<div style='background:#aaf'>Code for class");

      Object.extend(klass, Class.Methods);

      // *** Adding method missing support functions ***
      Object.extend(klass.prototype, {
        send: function(method) {
          var args = $A(arguments); args.shift();
          return this[method] ? this[method].apply(this, args) :
                                this.method_missing(method, args);
        },
        method_missing: function(method) {
          throw("method missing " + method);
        }
      });

      klass.superclass = parent;
      klass.subclasses = [];

      if (parent) {
        var subclass = function() { };
        subclass.prototype = parent.prototype;
        klass.prototype = new subclass;
        parent.subclasses.push(klass);
      }

      for (var i = 0; i < properties.length; i++)
        klass.addMethods(properties[i]);

      if (!klass.prototype.initialize)
        klass.prototype.initialize = Prototype.emptyFunction;

      klass.prototype.constructor = klass;
      document.writeln("</div>");
      return klass;
    }
  };

  Class.Methods = {
    addMethods: function(source) {
      var ancestor = this.superclass && this.superclass.prototype;

      for (var property in source) {
        var value = source[property];
        if (ancestor && Object.isFunction(value) &&
            value.argumentNames().first() == "$super") {
          var method = value, value = Object.extend((function(m) {
            return function() { return ancestor[m].apply(this,
arguments) };
          })(property).wrap(method), {
            valueOf:  function() { return method },
            toString: function() { return method.toString() }
          });
        }

        // *** Replacing method calls this.f(x,y) with this.send('f',
x, y) ***
        value = value.toString().replace(/this\.([a-z_1-9]+)\(/g,
           function(ignore, method) { return "this.send('"+method
+"',";});
        document.writeln("<pre>" + value + "</pre>");

        this.prototype[property] = eval(value.toString());
      }
      return this;
    }
  };

  // A small method_missing javascript example

  var Person = Class.create({
    initialize: function(name) {
      this.name = name;
      document.writeln(this.say("I see the light.")); // Method
exists.
      document.writeln("<br/>");
      document.writeln(this.says("I'm born!")); // Triggers
method_missing.
    },
    say: function(message) {
      return this.name + ': ' + message;
    },

    method_missing: function() {
      return "You missed with (" + $A(arguments).join(", ") + ")";
    }
  });

  var john = new Person('Long John');
  // Will print
  // -> Long John: I see the light.
  // -> You missed with (says, I'm born!)


--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "Ruby 
on Rails: Spinoffs" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/rubyonrails-spinoffs?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to