Thursday, May 14, 2009

Custom Rake Tasks

I came across to write a custom rake script for my rails application. Because my application is rich client side application and doesn't use id for any of my models. Instead, it used UUID as a primary key. I got some problems while changing this, and one of them is rails rake commands such as rake db:test:prepare, rake test:functionals, .... For my application, these two commands didn't work really well since it makes my test database messed with autonumber id of all tables. Here, my rake script to load to my test database. Pay attention to mysql command, in this case, I need to run several commands inside mysql command.


task :load_test_db do
#load data to development
Rake::Task["db:fixtures:load"].invoke

#clone development to test
Rake::Task["db:test:clone_structure"].invoke

#pull data from development
sh "mysqldump > test.sql development_ncdd_templates -u root"

sh "mysql -u root << EOF
use test_ncdd_templates;
source test.sql;
exit
EOF"
end


If you want to run bash command, take this as an example. I'm not a expert of shell script, but it works for me anyway.

sh "#!/bin/bash
      cd lib
      ruby to_yml.rb
      cd .."

Here are some excellent sources:
http://www.railsenvy.com/2007/6/11/ruby-on-rails-rake-tutorial
http://railscasts.com/episodes/66-custom-rake-tasks

Wednesday, May 13, 2009

JavaScript in Object-Oriented Way

I conducted a training to some developers in my office about one full day, yesterday. It is quite exhausted anyway, but everyone seems understand really well. This slide covers many advanced features of JavaScript: Function, Object, Closure,.... Some other points I have pointed out in this slide are about how to make private variable, public variable, static variable, privileged variable and how to do inheritance. I took about 20 different sources as my references and three famous authors. It took me two weeks, at every weekend, to finish this slide.

Thursday, May 7, 2009

JavaScript Mixins

I have just reviewed JavaScript Design Patterns, and I think it is good to mention this.

It is possible to do a mixin class in JavaScript as in Ruby. This is another way to make our code reuse without inheritance. Consider you have a function, and you wish to use in many classes. In practice, you create a class that contains your general-purpose methods, and then use it to augment other classes. Class with these general-purpose methods is called Mixin class. It is generally not instantiated or called directly, instead it exists to provide methods to other classes.


var Mixin = function() {};
Mixin.prototype = {
   serialize: function() {
      var output = [];
      for(key in this) {
         output.push(key + ': ' + this[key]);
      }
      return output.join(', ');
   }
};


This sort of method could potentially be useful in many different types of classes, but it doesn’t make sense to have each of these classes inherit from Mixin. Similarly, duplicating the code in each class doesn’t make much sense either. The best approach is to use the augment function to add this method to each class that needs it:


augment(Author, Mixin);

var author = new Author('Ross Harmes', ['JavaScript Design Patterns']);
var serializedString = author.serialize();


This can be thought of as a way to implement multiple inheritance in JavaScript.


/* Augment function. */
function augment(receivingClass, givingClass) {
   for(methodName in givingClass.prototype) {
      if(!receivingClass.prototype[methodName]) {
         receivingClass.prototype[methodName] = givingClass.prototype[methodName];
      }
   }
}


A more robust augment allows copying one or two of them over to another class.

/* Augment function, improved. */
function augment(receivingClass, givingClass) {
   if(arguments[2]) { // Only give certain methods.
      for(var i = 2, len = arguments.length; i < len; i++) {
         receivingClass.prototype[arguments[i]] = givingClass.prototype[arguments[i]];
      }
   }
   else { // Give all methods.
      for(methodName in givingClass.prototype) {
         if(!receivingClass.prototype[methodName]) {
            receivingClass.prototype[methodName] = givingClass.prototype[methodName];
         }
      }
   }
}


You can now write augment(Author, Mixin, 'serialize'); to only augment Author with the single serialize method.

In other times, you don't have to need this augment function in order to do Mixins. You could do this by using apply or call method inside constructor function.


var Author = function(name, books) {
   this.name = name || "";
   this.books = books || [];

   Mixin.apply(this);
};


Often it makes more sense to augment a class with a few methods than it does to make
one class inherit from another. This is a lightweight way to prevent code duplication. Unfortunately, there aren’t many situations where it can be used. Only methods general enough to be used in very dissimilar classes make good candidates for sharing (if the classes aren’t that dissimilar, normal inheritance is often a better choice).

Prototypal Inheritance vs. Classical Inheritance

While it is possible to emulate classical inheritance like Java or C#, it is clear that we do prototypal inheritance by taking advantages of prototype lookup chains. Each has its own advantages and disadvantages. Here I quoted from JavaScript Design Patterns:

The classical approach to creating an object is to (a) define the structure of the object, using
a class declaration, and (b) instantiate that class to create a new object. Objects created in this
manner have their own copies of all instance attributes, plus a link to the single copy of each
of the instance methods.

In prototypal inheritance, instead of defining the structure through a class, you simply
create an object. This object then gets reused by new objects, thanks to the way that prototype
chain lookups work. It is called the prototype object because it provides a prototype for what the other objects should look like.

Instead of using a constructor function named Person to define the class structure, Person
is now an object literal. It is the prototype object for any other Person-like objects that you want to create. Define all attributes and methods you want these objects to have, and give them
default values.


/* Person Prototype Object. */
var Person = {
name: 'default name',
getName: function() {
return this.name;
}
};

var reader = clone(Person);
alert(reader.getName()); // This will output 'default name'.
reader.name = 'John Smith';
alert(reader.getName()); // This will now output 'John Smith'.


To create a new Person-like object, use the clone function. This provides an empty object with
the prototype attribute set to the prototype object. This means that if any method or attribute
lookup on this object fails, that lookup will instead look to the prototype object.
To create Author, you make a clone.


/* Author Prototype Object. */
var Author = clone(Person);
Author.books = []; // Default value.
Author.getBooks = function() {
return this.books;
}

var author0 = clone(Author);
author0.name = 'Dustin Diaz';
author0.books = ['JavaScript Design Patterns'];
var author1 = clone(Author);
author1.name = 'Ross Harmes';
author1.books = ['JavaScript Design Patterns'];

Here is the clone function. First the clone function creates a new and empty function, F. It then sets the prototype attribute of F to the prototype object. Lastly, the function creates a new object by calling the new operator on F. The cloned object that is returned is completely empty, except for the prototype attribute, which is (indirectly) pointing to the prototype object, by way of the F object.

/* Clone function. */
function clone(object) {
function F() {}
F.prototype = object;
return new F;
}


In classical inheritance, each instance of Author has its own copy of the books array. You could add to it by writing author1.books.push('New Book Title'). That is not initially possible with the object you created using prototypal inheritance because of the way prototype chaining works. A clone is not a fully independent copy of its prototype object; it is a new empty object with its prototype attribute set to the prototype object. When it is just created, author1.name is actually a link back to the primitive Person.name. When you write to author1.name, you are defining a new attribute directly on the author1 object.


var authorClone = clone(Author);
alert(authorClone.name); // Linked to the primative Person.name, which is the
// string 'default name'.
authorClone.name = 'new name'; // A new primative is created and added to the
// authorClone object itself.
alert(authorClone.name); // Now linked to the primative authorClone.name, which
// is the string 'new name'.
authorClone.books.push('new book'); // authorClone.books is linked to the array
// Author.books. We just modified the
// prototype object's default value, and all
// other objects that link to it will now
// have a new default value there.
authorClone.books = []; // A new array is created and added to the authorClone
// object itself.
authorClone.books.push('new book'); // We are now modifying that new array.


Classical inheritance is well understood, both in JavaScript and the programmer commu-
nity in general. Almost all object-oriented code written in JavaScript uses this paradigm. If you
are creating an API for widespread use, or if there is the possibility that other programmers not
familiar with prototypal inheritance will be working on your code, it is best to go with classical.

JavaScript is the only popular, widely used language that uses prototypal inheritance, so odds
are most people will never have used it before. It can also be confusing to have an object with
links back to its prototype object. Programmers who don’t fully understand prototypal inheri-
tance will think of this as some sort of reverse inheritance, where the parent inherits from its
children. Even though this isn’t the case, it can still be a very confusing topic. But since this
form of classical inheritance is only imitating true class-based inheritance, advanced JavaScript
programmers need to understand how prototypal inheritance truly works at some point any-
way. Some would argue that hiding this fact does more harm than good.

Subscribe in a Reader