Monday, December 20, 2010

Bundler for ruby applications

I just found out that Rails3 is using Bundler to manage all of the gem dependencies.

This is just an awesome idea ;-)

I use to write custom deployment script for all of the new instances that I create in the cloud.

With this, you can easily manage the dependencies for your ruby application anywhere you choose to run.

Include ruby json gem into Rails3 automatically

First, install the gem from command line.
> sudo gem install json
Then, add the following line to Gemfile
gem 'json'

How to autoload libraries from lib directory for Rails3

Inside application.rb
module ApiServer
  class Application < Rails::Application
    # Custom directories with classes and modules you want to be autoloadable.
    # config.autoload_paths += %W(#{config.root}/extras)
    config.autoload_paths += %W(#{config.root}/lib) 
  end
end

Thursday, December 31, 2009

How to mimic apache's "!-f" and "!-d" in lighttpd

Just a while ago, I was still trying to write a php script to load static content and send them to browser, now that I know apache has a nice rewrite condition like this:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d<
RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]
I don't have to use that script of mine any more. However, I hit the wall straight on when I was trying to port the same functionality in lighttpd, and the only thing I found was
url.rewrite-[repeat-]if-not-file
Only half of the solution, and it somehow stopped working for me after working or 2 weeks, and says
WARNING: unknown config-key: url.rewrite-if-not-file (ignored)
gerrr.....

That did it ;-) I was determined to find the right solution to finish this for good, and here is what I have found:

Using mod_magnet and a small lua script. For detail, see the following urls.

http://www.akelos.org/wiki/setting-up-akelos-on-lighttpd-in-a-mac
http://redmine.lighttpd.net/projects/lighttpd/wiki/AbsoLUAtion

Oh, if you happen to be on ubuntu, you would probably also need to do this
sudo apt-get install lighttpd-mod-magnet

Monday, December 28, 2009

ubuntu's rc management

I hate to write these down, but I have been using these so often this winter break that I can't allow myself to do another search to find the answers.

To stop apache2 for this session only:
sudo /etc/init.d/apache2 stop

To remove apache2 permanently from startup scripts:
sudo update-rc.d apache2 remove

To reinstate apache2 in the startup scripts:
sudo update-rc.d apache2 defaults

Friday, April 4, 2008

jsdIScript

I was in the process of trying to figure out how to track the stack frames in javascript through jsd, and naturally, I wanted to see what's in jsdlScript ;-) So I hooked a logging method in the script enumerator, and found out that at least in Mozilla, javascript is counted in the unit of functions. Each function is treated as a jsdlScript object. This makes a lot of sense. (Well, not that it didn't make any sense.) It also explains, if a page has javascript files from different servers, it cannot distinguish the scripts origin based on the url of the file. Well, more fun for me working with the jsd ;-)

Wednesday, March 26, 2008

How to work with jsd (Javascript Debugger)

I was really determined to figure out how firebug and venkman works, so I can write a javascript walker or stepper for my firecruncher plugin. The further I investigate, the more I respect the authors and contributors of these two pieces of seriously written software.

I started with the UI, and then I headed for the core that interacts with the xpcom compionent jsd (Javascript Debugger).

It never seamed easy for me, even though there are some sparse documentation in xulplanet, but the only two examples that I was able to consult was
It really took me a while figuring out how jsd works, as both of the source above have thousands of lines of javascript, a lot of them has interactions with objects outside of the classes or services that are defined in the same file.

After a week's worth of night reading, prototyping and code porting, I finally got it. Well, most of it. ;-)

It turns out that using jsd isn't that hard at all if you know Javascript's event handing mechanism. Well, in jsd, the original designer called them hooks. There are hooks for almost everything from the creation and destruction of a script, errors, to function call and program counters (interrupt or execution). Just think of them as different events that will be fired during a debugger active session. All what we need to do is to write the appropriate handers, and hook back into the jsd.

I will describe a common life cycle of the usage of jsd below:

First, we acquire the @mozilla.org/js/jsd/debugger-service;1 service.
var jsd = Components.classes["@mozilla.org/js/jsd/debugger-service;1"].getService(jsdIDebuggerService);
jsd.on();
Ref: http://www.xulplanet.com/references/xpcomref/ifaces/jsdIDebuggerService.html
With this, we can turn on, off, pause and unpause the debugger, but how do we set a break point? Ha, we are jumping ahead of ourselves. We need a piece of script first, so we can set the break point on top of it. Here is how you track which script has been created and which one has been destroyed.
jsd.scriptHook =
{
onScriptCreated: function(script){/* xxx track the scripts xxx */},
onScriptDestroyed: function(script){/* xxx track the scripts xxx */}
};
You can also enumerate all of the existing scripts that are available before the debugger was turned on by:
jsd.enumerateScripts({enumerateScript: function(script)
{
/* xxx track the scripts xxx */
}});
Now, we have all of the scripts available for us to set the break points. ;-)
Ref: http://www.xulplanet.com/references/xpcomref/ifaces/jsdIScript.html

That's all good until we encounter an error while running the script that we have loaded into the debugger. What do we do then? Ha, the ErrorHook comes handy.
jsd.errorHook = { onError: function(message, fileName, lineNo, pos, flags, errnum, exc){ /* xxx handle the error here xxx */ }};
You can do similar things with debuggerHook and debugHook. So what happens when we encounter a break point? Of course, there is a break point hook as well ;-)
jsd.breakpointHook = { onExecute: function(frame, type, val){ /* xxx handle the break point xxx */} };
We can do something at a break point now, but how do we temporarily suspend the code execution while we are at a break point, and do something like step over? It took me some search to figure this out ;-) We use enterNestedEventLoop to pause, and exitNestedEventLoop to get out of the paused state.
jsd.enterNestedEventLoop({onNest: function() { /* xxx another hook here, so we know that we are in a paused state xxx*/ });
jsd.exitNestedEventLoop(); // Yeh.. we are happily continuing our course of execution.
OK, we now can get a script, handle the error, set the break point, handle the break point, pause at the break point and continue from the break point. So how do we do the stepping? This is done by two other interrupts: functionHook and interruptHook ;-) In the case of step over, we use interruptHook, in the case of step out and step in, we use functionHook. (Ref below is copied from firebug-service.js)
hookFunctions: function()
{
function functionHook(frame, type)
{
switch (type)
{
case TYPE_FUNCTION_CALL:
{
++hookFrameCount;

if (stepMode == STEP_OVER)
jsd.interruptHook = null;

break;
}
case TYPE_FUNCTION_RETURN:
{
--hookFrameCount;

if (hookFrameCount == 0)
fbs.stopStepping();
else if (stepMode == STEP_OVER)
{
if (hookFrameCount <= stepFrameCount)
fbs.hookInterrupts();
}
else if (stepMode == STEP_OUT)
{
if (hookFrameCount < stepFrameCount)
fbs.hookInterrupts();
}

break;
}
}
}

jsd.functionHook = { onCall: functionHook };
},

hookInterrupts: function()
{
function interruptHook(frame, type, rv)
{
// Sometimes the same line will have multiple interrupts, so check
// a unique id for the line and don't break until it changes
var frameLineId = hookFrameCount + frame.script.fileName + frame.line;
if (frameLineId != stepFrameLineId)
return fbs.onBreak(frame, type, rv);
else
return RETURN_CONTINUE;
}

jsd.interruptHook = { onExecute: interruptHook };
},
That's it!