Image

Imageottercat wrote in Imagejavascript

DRY Accessor Helper

I got tired of creating accessor methods for properties (as well as the properties themselves!) in my javascript classes, so, taking a note from the prototype.js library, I wrote a helper which acts a little like ruby's attr_writer and attr_reader as well as method_missing. It's loosely based upon a MockObject class written by William Tayson at http://www.jadetower.org/muses/archives/000388.html.

The library itself does not have any dependencies, although I am (for convenience sake) using it with the prototype.js Object.extend() function in the example which follows.


// Accessors

// Based on an idea from William
Tayson ( http://www.jadetower.org ):


// "Bringing method_missing to
javascript" --


//
http://www.jadetower.org/muses/archives/000388.html


//

// To create a "mixin" for
accessor methods.


//

// Part of the Tarpaulin Project

//

// tarpaulin.rubyforge.org

//

// Written by ottercat --
ottercat@ottercat.net


//

// No dependencies on other code



// a helper function used below
by multiple functions/objects


function accessorWrapper(method){

    return
function(arg) {


    var
property=method.substr(3);


    var
mode=method.substr(0,3);


    if(mode ==
"get")


      {

  
       return this[property];


      }

    else

      {

  
       this[property]=arg;


      }

    }

}





// create both a getX() and setX()

function Accessors(properties) {

   
properties=properties.split(/[ \t\n]+/);


    for (var i=0;
i < properties.length; i++)


      {

     
this[properties[i]]="";


     
getter="get"+properties[i].substr(0,1).toUpperCase()+properties[i].substr(1);


     
this[getter]=accessorWrapper(getter);


     
setter="set"+properties[i].substr(0,1).toUpperCase()+properties[i].substr(1);


     
this[setter]=accessorWrapper(setter);


      }



}



// follow the ruby convention
here of creating a reader




function attrReader(attributes) {

   
properties=properties.split(/[ \t\n]+/);


    for (var i=0;
i < attributes.length; i++)


      {

     
if(this[attributes[i]] == undefined)


  
     {


      
 this[attributes[i]]="";


  
     }


     
getter="get"+attributes[i].substr(0,1).toUpperCase()+attributes[i].substr(1);


     
this[getter]=accessorWrapper(getter);


      }

}



// follow the ruby convention
here of creating a writer




function attrWriter(attributes) {

   
properties=properties.split(/[ \t\n]+/);


    for (var i=0;
i < attributes.length; i++)


      {

     
if(this[attributes[i]] == undefined)


  
     {


      
 this[attributes[i]]="";


  
     }


     
setter="set"+attributes[i].substr(0,1).toUpperCase()+attributes[i].substr(1);


     
this[setter]=accessorWrapper(setter);


      }

}



Here's test code, showing usage.....

var test={

  fred : "flintstone",

  tom : "jerry",

  foo : function() {
alert("test!");}


};



Object.extend(test,new
Accessors("name rank"));


test.setName("Barney Fife");

test.setRank("Deputy");

for (i in test)

{

document.write(i + "<br/>");

}

document.write(test.getName()+"<br/>");

document.write(test.getRank()+"<br/>");



I'll have this shortly posted to CVS, but what do you think?