- Posted by liammclennan on June 28, 2010
I read somewhere that Kent Beck likes to apply a strategy of taking a technique that works and exaggerating it, to see if the results are likewise exaggerated. He found that specifying the behaviour of components prior to implementation, and in small increments, produced good design, so he exaggerated it and now we have TDD. He found that strong engineering practices, rich communication and delayed decision making was a good way to run projects, so he exaggerated it and now we have Extreme Programming.
In homage to Kent Beck and his work I decided to apply his technique to web frameworks, taking the things that I like and exaggerating them. Here are some of the things that I value in a web framework:
- a rich language
- simplicity
- minimalism
- expressiveness
- opinionatedness
Using the above guidelines I sketched out an idea for a server-side framework for CoffeeScript. It is heavily inspired by Sinatra, with a few minor tweaks and coverted to CoffeeScript. Here is what a controller might look like:
# The first parameter is the route. Like sinatra, there is no route abstraction.
# The second parameter is a method to execute when the route is matched.
# Enforced one-model-in. No need for params[]
get '/', (input_model) ->
"Hello World"
# Views are found based on the name of the model passed to the view method.
# ? here is the CoffeeScript existential operator.
get 'address/:slug', (address_request) ->
if address_request?
@address = address_finder.find_by_slug address_request.slug
view @address
# View model objects are automatically given bind_to() and update()
# methods for binding to and from domain objects.
post 'address/create', (address_model) ->
@address: address_model.update new Address()
# do something with @address
@address_list = address_finder.all()
view @address_list
As promised the implementation described has some strong opinions: one-model-in, binding methods on view models and no route abstraction.
One-Model-In
One-model-in is a rule that no action may have more than one parameter. All request values (querystring, form, route) are mapped onto the input view model.
Binding Methods on View Models
The input view model objects are automatically given bind_to() and update() methods. By extending the base view model class developers can create more sophisticated view models.
view_model_object.bind_to(domain_object)
Bind to copies the attributes of the input domain object to the view model object.
view_model_object.update(domain_object)
Update copies the attributes of the view model object to the domain model object.
No Route Abstraction
Most MVC web frameworks have an abstraction for routes, meaning that a url is mapped to a route and the route is mapped to a controller action.
Url <—> Route <—> Action <—>
Sinatra simplifies by omitting the route abstraction, and I have too. The advantage is simplicity, the disadvantage is that refactoring an application’s URL scheme might be more difficult.
- Posted by liammclennan on June 17, 2010
Just because I like to build things, and I like to learn, I have been working on a keyboard shortcut reference site. I am using this as an opportunity to improve my ruby and rails skills.
The first few days were frustrating. Perhaps the learning curve of all the fun new toys was a bit excessive. Finally tonight things have really started to come together. I still don’t understand the rails built-in testing support but I will get there.
Interesting Things I Learned Tonight
RubyMine IDE
Tonight I switched to RubyMine instead of my usual Notepad++. I suspect RubyMine is a powerful tool if you know how to use it – but I don’t. At the moment it gives me errors about some gems not being activated. This is another one of those things that I will get to. I have also noticed that the editor functions significantly differently to the editors I am used to. For example, in visual studio and notepad++ if you place the cursor at the start of a line and press left arrow the cursor is sent to the end of the previous line. In RubyMine nothing happens.

Haml
Haml is my favourite view engine. For my .NET work I have been using its non-union Mexican CLR equivalent – nHaml.
Multiple CSS Classes
To define a div with more than one css class haml lets you chain them together with a ‘.’, such as:
.span-6.search_result contents of the div go here

Indent Consistency
I also learnt tonight that both haml and nhaml complain if you are not consistent about indenting. As a consequence of the move from notepad++ to RubyMine my haml views ended up with some tab indenting and some space indenting. For the view to render all of the indents within a view must be consistent.
Sorting Arrays
I guessed that ruby would be able to sort an array alphabetically by a property of the elements so my first attempt was:
Application.all.sort {|app| app.name}
which does not work. You have to supply a comparer (much like .NET). The correct sort is:
Application.all.sort {|a,b| a.name.downcase <=> b.name.downcase}
MongoMapper Find by Id
Since document databases are just fancy key-value stores it is essential to be able to easily search for a document by its id. This functionality is so intrinsic that it seems that the MongoMapper author did not bother to document it. To search by id simply pass the id to the find method:
Application.find(‘4c19e8facfbfb01794000002’)
Rails And CoffeeScript
I am a big fan of CoffeeScript so integrating it into this application is high on my priorities. My first thought was to copy Dr Nic’s strategy. Unfortunately, I did not get past step 1. Install Node.js. I am doing my development on Windows and node is unix only. I looked around for a solution but eventually had to concede defeat… for now.
Quicksearch
The front page of the application I am building displays a list of applications.

When the user types in the search box I want to reduce the list of applications to match their search. A quick googlebing turned up quicksearch, a jquery plugin. You simply tell quicksearch where to get its input (the search textbox) and the list of items to filter (the divs containing the names of applications) and it just works. Here is the code:
$('#app_search').quicksearch('.search_result');
Summary
I have had a productive evening. The app now displays a list of applications, allows them to be sorted and links through to an application page when an application is selected. Next on the list is to display the set of keyboard shortcuts for an application.
- Posted by liammclennan on June 14, 2010
After more time than I care to admit I have finally released a rudimentary Http Handler for serving compiled CoffeeScript from Asp.Net applications.
It was a long and painful road but I am glad to finally have a usable strategy for client-side scripting in CoffeeScript.
Why CoffeeScript?
As Douglas Crockford discussed in detail, Javascript is a mixture of good and bad features.
The genius of CoffeeScript is to treat javascript in the browser as a virtual machine.
By compiling to javascript CoffeeScript gets a clean slate to re-implement syntax, taking the best of javascript and ruby and combining them into a beautiful scripting language. The only limitation is that CoffeeScript cannot do anything that javascript cannot do.
Here is an example from the CoffeeScript website. First, the coffeescript syntax:
reverse: (string) ->
string.split('').reverse().join ''
alert reverse '.eeffoC yrT'
and the javascript that it compiles to:
var reverse;
reverse = function(string) {
return string.split('').reverse().join('');
};
alert(reverse('.eeffoC yrT'));
Areas For Improvement ;)
The current implementation is deeply flawed, however, at this point I’m just glad it works. When the server receives a request for a coffeescript file the following things happen:
- The CoffeeScriptHandler is invoked
- If the script has previously been compiled then the compiled version is returned.
- Else it writes a script file containing the CoffeeScript compiler and the requested coffee script
- The process shells out to CScript.exe to to execute the script.
- The resulting javascript is sent back to the browser.
This outlandish process is necessary because I could not find a way to directly execute the coffeescript compiler from .NET. If anyone can help out with that I would appreciate it.
- Posted by liammclennan on May 6, 2010
Tonight the Brisbane Alt.NET group is doing a coding dojo. I am hoping to talk someone into pairing with me to solve the kata in CoffeeScript. CoffeeScript is an awesome language, half javascript, half ruby, that compiles to javascript. To assist with tonight’s dojo I wrote the following micro test framework for CoffeeScript:
<html>
<body>
<div>
<h2>Test Results:</h2>
<p class='results' />
</div>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js" type="text/javascript"></script>
<script type="text/coffeescript">
# super simple test framework
test: {
write: (s) ->
$('.results').append(s + '<br/>')
assert: (b, message...) ->
test.write(if b then "pass" else "fail: " + message)
tests: []
exec: () ->
for t in test.tests
test.write("<br/><b>$t.name</b>")
t.func()
}
# add some tests
test.tests.push {
name: "First Test"
func: () ->
test.assert(true)
}
test.tests.push {
name: "Another Test"
func: () ->
test.assert(false, "You loose")
}
# run them
test.exec(test.tests)
</script>
<script type="text/javascript" src="coffee-script.js"></script>
</body>
</html>
It’s not the prettiest, but as far as I know it is the only CoffeeScript test framework in existence. Of course, I could just use one of the javascript test frameworks but that would be no fun. To get this example to run you need the coffeescript compiler in the same directory as the page.