1/29/2009

Prototype Ajax Responders - Disabling

The Prototype Ajax API allows us to make requests to our web servers very easily. It also supports Responders that allow you to declare standard behaviors to occur before and after your Ajax calls, like show the spinning ball and dim the page and fun things like that.

The nice thing about this approach is that you don't have to worry about setting up these behaviors around your send and receive methods for each call. Instead, they just work, until you don't want them to.

I have a session timeout popup that needs to submit an Ajax request to tickle the server session stopping it from timing out. I do not want my standard behaviors occurring since this is not a modal interaction like all my other Ajax calls.

What I need to do is let my "responders" know that this is not a call that I want handled. This is my standard Ajax API that wraps the prototype call. As you can see, I am enforcing a json interface to the callback supplied by my application.

var Url = Class.create(
{
get: function(a_url, a_callback)
{
new Ajax.Request(a_url,
{
method :'get',
onSuccess : function(a_transport)
{
var json = eval(a_transport.responseText);
a_callback(a_transport, json);
}
});
}
});

The behaviors I am using are simple dimming of the background and the usual spinner image.

Ajax.Responders.register(
{
onCreate : function(a_request)
{
if (Ajax.activeRequestCount >= 1)
{
document.body.addClassName('ajax-processing');
new Popup('spinning_wait',null,
{
position: 'screen',
modal:true,
effect: 'blink'
}).show();
}
},
onComplete : function(a_request)
{
if (Ajax.activeRequestCount == 0)
{
$('spinning_wait').popup.hide();
document.body.removeClassName('ajax-processing');
}
}
});

So the problem is how do I specify, at call time, whether a specific Ajax call should be modal or not. Fortunately, the Prototype library passes the options to your Responders so that you can push in variables as you like.

To do this add your own options to your Prototype Ajax call.

new Ajax.Request(a_url,
{
my_custom_modal_option: true,
...
});

And in your handlers you can access this custom option.

onCreate : function(a_request)
{
if (a_request.options.my_custom_modal_option)
{
...
}
}

You can of coarse pass in any property name to drive any kind of behavior you like.

1/24/2009

2D, 3D and 4D Languages

If you are looking for something about graphics, then go away. Nothing of interest here.

I want to coin some terms that allow us to describe the languages we use. Nothing fancy but we might find it useful to limit the pro/con discussions and abstract them to something simpler.

We have talked bout 3rd Generation and 4th Generation languages to allow us to conceptualize the abstractions at the language level as opposed the class level. 4G languages are still being sold by those after some money but continue to be generally despised by programmers that can't make them do what they need.

OK, so why add the concept of a dimension here? Well, it probably has something to do with how my mind works and is not necessarily anything anyone else might share but when you say "refactor these lines into another method" I see that as a vertical or horizontal shift in behavior. Perhaps they are being generalized into a base class, vertical obviously, or moved into a delegate class that would be a right shift. These are 2D movements performed in all languages but C, for example, is limited to these kinds of adjustments.

Some languages are able to move along the Z axis. Object Oriented languages add to the 2D shifts the ability to distribute behaviors across instances, while not being able to vary behavior along this axis they are varying state and therefore execution paths vary by vertical plane. Each layer represents a keenly scoped set of behaviors driven by the state passed in. These are cones of execution, from a single method entry point at the tip of the cone, the state is distributed out across a set of associated instances to apply the appropriate behavior.

These 3D models become more complicated when you consider how some line of code inside a cone might throw an exception that provides a pipe to some layer of your application, in-front-of and left-of the throw point. It produces a hole in the side of the cone where flow can pass to another location.

Cones are contained within other cones of coarse, the applications main method being the pointy end of the outer cone. The API design rules we apply like no globals, no leaky abstractions, scope actions on state within their own class, all go to explain why no cone sides should ever intersect.

If you are still with me, then on we move to the 4th Dimension. I don't know how you conceive this in real space but I tend to look at the time dimension as a set of invisibility cloaks. As you move forward throw the cloaks, the last set of 3D stuff you were looking at disappears and another set appears. Presumably, we could move backwards to start seeing back in time.

Well Ruby, and other dynamic languages, have started playing with this dimension. Each instance, executing it's methods in it's cone, can be changed at runtime. A call to File.new here is different from the same call there. This allows us to evolve what is being executed based on state, time or idle whim. Code is data, data is code.

Now these concepts have some evolution ahead of them since these changes are made at "indiscreet points" at the moment. So I have to make the change and then execute that change. I can't encapsulate a change and an execution into a single language concept but these are just the semantics we play with today.

Behind each invisibility cloak is a 3D model of a runtime. Each model contains a set of finite behaviors and their changing state. Any statement that mutates it's own behavior, creates an invisibility cloak.

Don't confuse these with threads. Threads are shiny, sparkly little stars, like the sparklers from fireworks night, that run around your 3D cones doing stuff. There may be many of these things in a single 2D or 3D model, all buzzy and excitable. Some running around the same cone, trying to find your threading bugs for you but as long as your cones don't have cracks you will be fine.

When you hear Ruby programmers arguing about that there are no static methods in Ruby, what they are saying is that Ruby is a 4D language and the person they are arguing with only knows 3D languages. It's just like the old arguments that prompted 2D experienced people to say that we could do anything in C that you could do in C++. Yes, I used to argue that one back in the day. Fundamentally true only because it's also true that you can build a house with matchsticks if you really, really wanted to.

Ruby offers far more than just it's 4D features. Open classes, modules and closures are different ways to describe static, 3D concepts. A language becomes 4D when it can vary it's behavior at runtime. This isn't a new concept on it's own. I used to write basic programs that added code as it ran 20 years ago but this is more than this simple concept.

When we look at programming we talk less about the detailed syntax of how features are coded and more at the best constructs that survive change and optimize re-usability. We don't have many strategies defining how to mutate code as it runs to augment the runtime model that is executing.

The best proof that I don't know what I am doing in 4D is to look at the invisible cloak. I think this shape needs to change to better describe the scoped change that a piece of behavior might adopt.

I wonder what 5D means?

1/22/2009

BDD test framework Shoulda

Behavior Driven Development is an interesting slant on testing. There appear to be many opinions on its advantages and disadvantages. At the end of the day, if you are testing, you have already won.

So, the question is, how can you tweak your method to improve on your bugs-per-line-of-code metric. This post isn't about that because I have no idea if BDD or Shoulda will help.

Shoulda is an alternative BDD framework to RSpec that has been argued about for so long. I can't help you with that either.

Instead, I just started using Shoulda in a Rails app so thought I would share some complaints, because being constructive is just too much work.

I switch a simple controller test over to Shoulda and it ran and passed but the original 3 tests that used to pass are now reported as "0 tests, 0 failures, 0 errors". While I proved that if there was an error it did explain precisely what was wrong to me, this 0 tests thing is severely demotivating. It is amazing how watching the number of tests grow in your project can encourage you to continue to strive for perfection.

IDE integration is always a problem with new stuff. NetBeans allows me to run a single test case with ctrl-shift F6 which is convenient if you have few that are suddenly failing. No such luck with the Shoulda version, all tests all the time.

However, all this is trivia compared to being able to do something like this:

require 'test/unit'
require 'shoulda'

class Lion
def speak
"rarrrr hickup"
end
end

class TestLion < Test::Unit::TestCase

context "the lion" do
setup do
@lion = Lion.new
end

should "say rarrr" do
assert_equal "rarrr", @lion.speak
end
end
end

and get this explanation of what you did wrong.

1) Failure:
test: the lion should say rarrr. (TestLion):
<"rarrrr"> expected but was <"rarrr hickup">.

Craft your feedback as carefully as you craft your output.

1/20/2009

Definition of old technology

A technology is old when Google returns forum hits with answers that have since been deleted from the forum.


Struts 1 still blows.

1/03/2009

Christmas 2008 Connections

Another slant on this holiday period. Our family combined presents this year and find ourselves with a new 40" LCD 1080p TV, cheap by comparison. Expensive were the new cabinet required to hold it, cables to plug it in and investment in time admiring the details of the baby wilder beasts eyelashes as the croc eats them off.

Well this post is about connections because it seems all I have done is work out how to connect apparently useful devices together to produce alternate results. Lets start with the new WII.

The best way to by a WII is to purchase your kids college education using the National City Bank card and then use the points you accrue to invest in a gaming system to take your mind off the amount of money it cost you. So this "free" WII was plugged in using a low def composite cable (1) since Mario in low detail is still Mario.

The WII is internet connectable so that you can use the WII Shop online, oh how convenient that is. So a simple DHCP connection to the Linksys wireless router (2).

The welcome screen of the WII shows a set of "channels" to select. One is the CD with the game you plugged in last, another the WII Shop Online channel. Well if you head off to this shop you are offered additional channels to purchase in the "point" currency. Each "point" is equivalent to 1 cent US so the fact that it is a "point" only serves to help you forget you are spending real money. One of the items to purchase for a very reasonable 500 points is the "Internate Channel". I could not resist (3). What it appears to do is download and install a cut down version of the Opera browser into your WII so that you can navigate the web with with the WII remote. No flash, no video support but very large buttons to shoot with your WII remote. On the whole not a bad experience.

I needed to backup my Mac so invested in a Time Capsule which is a little white box that you plug some power into and hey presto you have backup (4). My first full backup took 27 hours. Needless to say the wireless part has a down side, however, now that it is just doing delta backups it is great. The Time Capsule is also a wireless access point but it didn't seem necessary to add a third subnet to the house.

A long time ago I was lucky enough to win a high end XBox from the Cincinnati DotNet User Group. Well it was finally time to crack the seals and see what she could do. A special high definition connection to the TV with the switch on the side of the cable set appropriately (5) gave us an excellent view of videos and music that we could buy if we wanted to. See, I only buy things that give me the option to buy more. If only Paulson could have come up with this strategy.

It didn't end there, with all these things to buy, what should one choose? Oh yes, Netflex, instant streaming of high def video through my XBox onto my TV, what could be better. Plus, bonus of bonuses, free for the first two weeks. I am in (6).

To hook up Netflix Instant Viewing through your XBox is not too hard but does require a little "out of the box" thinking. Firstly, spool through the stream of adverts that the new horrendous XBox console throws at you until you find the randomly inserted Netflix. Sometimes it doesn't appear, so you have to go out and back in until the right random ad appears. I was persistent enough to beat the ad rampage.

Once you click on this ad it downloads and installs something magical on you XBox that does nothing. Well I say nothing because it didn't do anything except tell me to go and find my computer and access the Netflix web site to create an account and enter a six character code.

Once you have created your account and entered all your relevant bank draining information you are ready to go. The first thing we did was go back to the XBox and try to work out how to get a selection of movies. That will not work. Don't do it. Wastes lots of time and there is likley some frustrated screaming and a little cussing going on as well. I feel sure this is in the Netflix business goals, "Maximise setup frustration to optimize relief when complete".

Instead, stay on the Netflix web site and select the movies you want to watch. Don't "Play" them even if it asks you to, that will just show them on your PC. Don't "Add" them because that means they will be arriving in the mail in a few days. Instead you have to find the few movies available for "instant viewing", hover over the "Add" button (don't click it), and a secret menu opens up inviting you to add the movie to your "instant queue".

Finally, with movies in your instant queue you can go back to your XBox controller and they will appear in the list of available moves to watch. Note, to go back into that list on the XBox later you will have to go and find the randomly displaying Netflix advert which offers you the opportunity to practice your zen deep breathing. We chose "Then she found me", some might call a chick flick but I call a delightful romp through the hideous decisions people make when in love.

Connection (7) is the XBox Extender which allows me to use the Media Center app on our little, slow, wireless connected laptop as a movie streaming hub. Yes, you guessed it, it's damned slow. However, we did find a nice use for it. It will play a slideshow of all the photos you have on your PC which allowed us a few minutes of joy with the "oohs" and "aaahs" and "do you remember that? No? Damn it thats were we met?" moments of our past.

The next connection is to my Mac Book Pro. Another $20 and I am in posession of a fine looking cable, kindley posted to me by my friend Apple. This connects the DVI port on the Mac with the HDMI port on the TV (8). The 17" laptop screen runs at 1920x1200 and the 40" TV runs at 1920x1080 interlaced. So if my post Christmas figurin' is anything to go by, a TV pixel is 2.3 times bigger but only 9/10ths the relative height. This makes for a grainy hard to read image that I can't distinguish the "i"s and "l"s on.

The last planned connection is a 17" 5x7 LCD picture frame to a 4G SD card from our camera (9). This was my present to my wife, the idea is, and note, this is how you make cool techy gagits romatic, that each time a pictures changes a new emotion enters the room. Say it together, aaahhhh.

The moral of this story is that connected life is an amuzing way to while a way a cold Christmas week.

Christmas 2008

Yes, it happened again.

3 days ignoring family squabbles,
1 day opening presents and contemplating their impact to debt,
2 days loosing battles with chocolate covered cherries,
1 additional day loosing the battle with Bourbon Fudge,
2 days contemplating why we do this,
3 days rebelling against productivity, staying up till 3am watching bad movies,
1 day realizing that time is running out so, re-insulated the attic to R49, replaced two windshields and a failing septic tank motor. Oh, correction, watched hard working people do these things.
1 day remembering how lucky we are,
The last day noting that this is going to happen again next year and there is nothing you can do about it so just smile, damn it.