Introducing Lego

For a while now Mathias and I have been hacking away on our very own web framework called Lego.
But why? I hear you cry, why yet another one, what’s wrong with Rails, Merb, Ramaze, Sinatra, Camping, Rango, Waves, Mack, and so on and so on.
Well, they’re all great but we believe they aren’t dumb enough!
Lego however is about as dumb as it gets, all it knows is how to handle the request/response cycle and leaves the rest up to plugins.
The downside of this approach is that it takes a little bit more work to get it up and running the upside is that you get exactly what you want, nothing more, nothing less.

I’m intrigued, tell me more

So at it’s core there’s lego-core which contains only the bare essentials, a way to set up a controller that rack can run, and a way to extend the various parts of lego.

Future plans include a lego-more gem already setup with commonly used plugins so you easily can get up and running quickly and a central repository of available lego plugins.

A simple application

Provided that you have lego-core installed (gem install lego-core) put the following in a config.ru file:

1
2
3
4
5
6
require 'rubygems'
require 'lego-core'

class MyApp < Lego::Controller; end

run MyApp

Run it with rackup and point your browser to http://localhost:9292/ and you should be met by a plain old ‘404 – Not found’, not terribly exiting right? But that’s pretty much all lego-core gives you :)

So what about those plugins?

The lego extension system allows you to hook into various parts of the execution chain, namely:

View – For action and view related stuff
Controller – For defining controller dsl’s
Router – Rules for how lego should match routes, must have a self.match_route method which takes a route and an env parameter and return either a two element array containing the env and a hash of match data (or an empty hash if no match data is available) or false

At it’s core, a plugin is a module that responds to register who’s responsibility is to register with lego, following is a simple plugin example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
module SamplePlugin

  # Register is called by lego when plugin is loaded

  def self.register(lego)
    lego.add_plugin :view, View
    lego.add_plugin :router, Matcher
    lego.add_plugin :controller, Routes
  end

  # A plugin module we load as a view helper

  module View
    def h1(content)
      "<h1>#{content}</h1>"
    end
  end

  # A very simply route helper

  module Routes
    def get(path, &block)
      add_route(:get, {:path => path, :action_block => block})
    end
  end

  # A very simple route matcher

  module Matcher
    def self.match_route(route, env)
      (route[:path] == env['PATH_INFO']) ? [env, {}] : false
    end
  end
end

It’s about time for a real example!

As we showed you earlier, lego-core gives you a way to set up an application but it don’t know how to map routes to action so let’s expand on the previous application with our newly gained knowledge of lego’s extension system:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
require 'rubygems'
require 'lego-core'

module Routes
  def self.register(lego)
    lego.add_plugin :controller, SinatraController
    lego.add_plugin :router,     SimpleRouter
  end

  # implements a basic Sinatra inspiered dsl
  module SinatraController
    def get(path, &block)
      add_route(:get, {:path => path, :action_block => block})
    end
  end

  # Implements a very basic mather rule
  module SimpleRouter
    def self.match_route(route, env)
      (route[:path] == env['PATH_INFO']) ? true : false
    end
  end
end

# define an application
class MyApp < Lego::Controller
  plugin Routes
 
  get "/" do
    "Hello from /"
  end
end

run MyApp

As before, run it with rackup and point your browser to http://localhost:9292/ and this time you should be greeted by “Hello from /”.

Don’t repeat yourself

If you have a plugin you want to use in every application, then consider defining it globally:

1
2
3
4
5
6
7
8
9
  Lego.plugin MyPlugin

  # or group multiple plugin calls in a config block

  Lego.config do
    plugin MyViewPlugin
    plugin MyControllerPlugin
    plugin MyRouteMatcherPlugin
  end

Configuration options

Lego also comes with a very simple configuration handler, it basically provides two methods, set and options, lets look at them in action:

1
2
3
4
5
6
7
8
9
class MyApp < Lego::Controller
  plugin Routes

  set :foo => "bar", :baz => "quux"

  get("/foo") { options :foo }
 
  get("/bar") { options :bar }
end

As with plugins you can use set globally:

1
2
3
4
5
6
7
8
  Lego.set :foo => "bar"

  # or group multiple set calls in a config block

  Lego.config do
    set :foo => "bar"
    set :baz => "quux"
  end

Wrapping up

In conclusion Lego is a ‘Use what you want’ framework that tries to stay out of your way as much as possible and thank’s to it’s modular design, you are free to use your favourite technologies and tools.

Please note that it’s still in a highly experimental stage!

Posted in Programming, Projects, Ruby, gems at January 13th, 2010. No Comments
Tagged with , , , , . Written by: Patrik Hedman

Whilst being an object-oriented language, JavaScript still takes a lot of ideas from functional languages. One which it dosen’t implement though, is the idea of currying.
What’s currying then? You might ask, well, here’s the definition according to wikipedia:

In mathematics and computer science, currying, invented by Moses Schönfinkel and later re-invented by Haskell Curry,[1] is the technique of transforming a function that takes multiple arguments (or more accurately an n-tuple as its argument) in such a way that it can be called as a chain of functions each with a single argument.

So basically, it let’s you fill in some arguments to a function before hand and return a new function which you will subsequently call instead, or default arguments on steroids if you will.
Here’s a few examples of what we could do if JavaScript was capable of currying:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// Array to csc
Array.prototype.arrayToCsv = Array.prototype.join.curry("; ");

["Patrik", "Hedman", "Stockholm"].arrayToCsv(); //=> "Patrik; Hedman; Stockholm"


// And back
String.prototype.csvToArray = String.prototype.split.curry(/;\s*/);

("Patrik; Hedman; Stockholm").csvToArray(); //=> ["Patrik", "Hedman", "Stockholm"]


// The undefined parameter will be replaced with the
// callback function passed to clicker();
var clicker = document.body.addEventListener.curry("click", undefined, false);
clicker(function(){
    console.log( "Curryfied click event." );
});

Pretty sweet, but it wont work since there is no curry() function in JavaScript, not a problem, implementing one is pretty straightforward:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Function.prototype.curry = function() {
    // Save references to this and the arguments so we can
    // acces them from the closure
    var fn   = this,
        args = Array.prototype.slice.call( arguments );
                   
    return function() {
        var arg = 0;
        for ( var i = 0; i < args.length && arg < arguments.length; i++ )
            if ( args[i] === undefined )
                // If the original argument is undefined
                // then replace it with the new one
                args[i] = arguments[arg++];

        // Call the original function with the current this as
        // the context and the newly constructed argument list
        return fn.apply(this, args);
    };
};
Posted in JavaScript, Programming at November 8th, 2009. No Comments
Tagged with , , . Written by: Patrik Hedman

So, a few days ago I finally decided to give JavaScript a proper chance and as it turns out; All those people who’s been blabbering on about how JavaScript actually is a very powerful language where right all along!

You see, just like Ruby, JavaScript is extremely flexible, for instance, here’s how you would typically loop over an array:

1
2
3
4
var myArray = [1, 2, 3, 4, 5];
for (var i=0; i < myArray.length; i++) {
    alert(myArray[i]);
};

However, in Ruby land we’ve grown to know and love the [].each { |elem| … } way of looping, JavaScript doesn’t have that but fortunately adding it yourself is trivial:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// Extend the Array object with an each function
Array.prototype.each = function(fn) {
    // Loop through each element in this (which will be the
    // array instance we call each on)
    for (var i=0; i < this.length; i++) {
        // Call the callback function with it's context
        // set to the current array element
        fn.call(this[i]);
    };
};

// With our new each function in place we can now iterate
// over an array like this
[1, 2, 3, 4, 5].each(function() {
    alert(this);
});

Now, even though this is a very simple example, it does give you an idea of just how powerful of a language it really is, and while it’s not as pretty to look at as ruby, thereof the unfortunate disguise, dismissing JavaScript as a toy language just isn’t viable any more.

Posted in JavaScript, Ruby at October 28th, 2009. No Comments
Tagged with , . Written by: Patrik Hedman

She’s not wrapped in flash
all she wants is her java and a shell to bash
While, she’s a sight to C, plus
Her smile glimmers just like a Ruby does

You just gotta love it :)

Posted in Uncategorized at September 2nd, 2009. No Comments
Written by: Patrik Hedman

So, last night I upgraded my dev machine to Snow Leopard and what kind of a dev machine would it be without Vim?
Fortunately, for some at least, OS X still ships with Vim precompiled, unfortunately for me tough it still don’t come with ruby support enabled.

Since MacVim, which I usually use, isn’t yet compatible with Snow Leopard I decided to try and compile the regular vim as Mathias explained in a previous blog post about compiling for leopard, well that attempt crashed and burned. I did however get it to compile correctly after a minor tweak to his instructions:

On line 7 in src/auto/config.mk I changed the following line:

1
LDFLAGS   = -L. -arch i386 -arch x86_64

To look like:

1
LDFLAGS   = -L. -arch x86_64

While it did compile successfully, launching Vim just resulted in it exiting immediately with the message: abort trap.

Back at square one I started browsing the vim_mac mailing list and here’s how I finally got it working:

Start off by cloning the macvim repository:

1
~ $ git clone git://repo.or.cz/MacVim.git

Then change into the MacVim/src directory and configure and run make:

1
2
3
~ $ cd MacVim/src
MacVim/src $ ./configure --enable-gui-macvim --enable-rubyinterp
MacVim/src $ make

Now change into the MacVim directory:

1
MacVim/src $ cd MacVim

Normally this is where you would run xcodebuild, however that resulted in the following:

1
2
3
4
5
** BUILD FAILED **
The following build commands failed:
MacVim:
PhaseScriptExecution "Make Document Icons" /Users/pmh/Downloads/MacVim/src/MacVim/build/MacVim.build/Release/MacVim.build/Script-1D1C31F00EFFBFD6003FE9A5.sh
(1 failure)

The way to get around this is a bit cumbersome, but works.

Start by deleting line 6 in the Makefile that lives under the icons directory:

1
2
3
MacVim/src/MacVim $ cd icons
MacVim/src/MacVim/icons $ vim Makefile
# delete line 6 and save

Then change line 22 in make_icons.py, in the same directory, from:

1
dont_create = False

to:

1
dont_create = True

Change back to the MacVim directory and run xcodebuild:

1
2
MacVim/src/MacVim/icons $ cd ..
MacVim/src/MacVim $ xcodebuild

You should now see something like the following:

1
2
PyObjC not found, only using a stock icon for document icons.
 ** BUILD SUCCEEDED **

Now move the MacVim.app to the /Applications folder:

1
MacVim/src/MacVim $ mv build/Release/MacVim.app /Applications/

In order to invoke vim from the command line you need to add the following alias to your ~/.profile or what have you:

1
alias vim=/Applications/MacVim.app/Contents/MacOS/Vim

Note however that this only lets you use the command line version of MacVim, there seems to still be some issues with the graphical one.

Update:
As Björn pointed out in the comments, the graphical version of MacVim does work under Snow Leopard, also be sure to checkout his precompiled binary

Posted in Mouseless, Operatingsystem, Utilities at September 1st, 2009. 2 Comments
Tagged with , , . Written by: Patrik Hedman

If you, like me, are tired of vim’s pesky backup and swap files littering your project directory then you too should create a .vimtmp directory in your home folder and add this little snippet to your .vimrc

1
2
3
" Store vim backups and *.swp files in ~/.vimtmp with a unique name
set backupdir=~/.vimtmp//
set directory=~/.vimtmp//

Now all your backup and swap files will be stored in ~/.vimtmp/ and prefixed with a formatted file path, eg, %some%where%on%my%computer%some_file.ext.swp

Posted in Utilities at August 17th, 2009. 2 Comments
Tagged with , , . Written by: Patrik Hedman

So in order to save your fingers the pain I updated the ffmpeg gem today. You see, previously you had to do this:

1
2
3
convert "finding_that_nemo_dude.avi", :to => "finding_that_nemo_dude.flv" do
  ...
end.run

Doesn’t look to bad, right? Well, maybe not, but if you pay attention you would notice some repetition here, since the only thing different about the filenames is the extension. So, to keep things nice and dry you can now do this instead:

1
2
3
convert "finding_that_nemo_dude.avi", :to => :flv do
  ...
end.run

The old way still works if you really want a different filename all together or if you just really like to type :)

Posted in Ruby, Utilities, gems at August 15th, 2009. No Comments
Tagged with , , , . Written by: Patrik Hedman

Test::Unit is great but, of course, it’s designed to work everywhere and so it isn’t tailored to your specific domain. Fortunately though, that’s not a problem since adding your own custom assertions is as easy as creating two methods in your test helper.

Let’s say you have the following class:

1
2
3
4
5
class Polly
  def is_awesome?
    true
  end
end

And you wan’t to test whether Polly is awesome, which isn’t something you normally would have to test since I obviously am, but bare with me :) So you would do something like this:

1
2
3
4
5
6
7
8
9
class PollyTest < Test::Unit::TestCase
  def setup
    @polly = Polly.new
  end

  def test_that_polly_is_awesome
    assert @polly.is_awesome?
  end
end

Or, you could write a custom assertion to test whether any given object is awesome or not:

1
2
3
4
5
6
7
8
9
10
11
12
13
def assert_awesome(obj, msg=nil)
  msg ||= "Excpected #{obj.inspect} to be awesome"
  assert_block msg do
    obj.is_awesome?
  end
end
   
def assert_not_awesome(obj, msg=nil)
  msg ||= "Excpected #{obj.inspect} not to be awesome"
  assert_block msg do
    !obj.is_awesome?
  end
end

Now you could test awesomeness like this:

1
2
3
4
5
6
7
def test_that_polly_is_awesome
  assert_awesome @polly
end

def test_that_some_other_dude_isnt_awesome
  assert_not_awesome @some_other_dude
end

Custom assertions are great for making tests cleaner and easier to read, but don’t go crazy with them, testing ones awesomeness, for example, might not be all that usefull :)

Posted in Ruby at August 10th, 2009. No Comments
Tagged with , . Written by: Patrik Hedman

FFmpeg is a great tool for recording, converting and streaming audio and video. It can, however, be quite cumbersome to use. For example consider the following command:

1
ffmpeg -i some_file.flv -ss 00:00:20 -t 00:01:30 -s hd1080 -aspect 16:9 some_file.avi

Now, even though this is a simple example, it’s still kind of hard to know exactly what it does, so you can imagine what it will look like once you need to accomplish more complex tasks. By contrast, here is the same example using my ffmpeg gem (gem install polly-ffmpeg):

1
2
3
4
5
6
7
8
9
10
require "rubygems"
require "ffmpeg"
include FFMpeg

convert "some_file.flv", :to => "some_file.avi" do
  seek       "00:00:20"
  duration   "00:01:30"
  resolution "hd1080"
  aspect     "16:9"
end.run

This is in my opinion much easier to understand and use.

For more information checkout the documentation and the source code

Posted in Ruby, Utilities, gems at August 5th, 2009. 2 Comments
Tagged with , , , . Written by: Patrik Hedman

I’m not going to explain what MacRuby is but here’s a short description from the projects website:

MacRuby is a version of Ruby 1.9, ported to run directly on top of Mac OS X core technologies such as the Objective-C common runtime and garbage collector, and the CoreFoundation framework. While still a work in progress, it is the goal of MacRuby to enable the creation of full-fledged Mac OS X applications which do not sacrifice performance in order to enjoy the benefits of using Ruby.

So, to get started you obviously need to install MacRuby, but fear not, the official website provides a graphical installer so it’s just a point-n-click operation.
In order for MacRuby not to interfere with previously installed ruby versions it prefixes all command-line executables with mac* (eg, macruby, macgem, macrake and so on) so you’ll want to keep that in mind.

Hello World

MacRuby comes bundled with HotCocoa, a idiomatic ruby interface to cocoa. Using HotCocoa makes it easy to write to write cocoa apps in your favorite text-editor so you don’t have to resort to XCode and Interface Builder.
But enough talking, it’s time for the mandatory “Hello World” app :)

In your text-editor of choice create a file called hello_world.rb and edit it to look like this:

1
2
3
4
5
6
7
8
9
require "hotcocoa"
include HotCocoa

application :name => "Hello World" do |app|
  window :title => "Hello World", :frame => [500, 500, 300, 100] do |win|
    win << button(:title => "Click Me!").on_action { NSLog "Hello World" }
    win.will_close { exit }
  end
end

And that’s it, now save the file and run it from the command-line like this:

1
$ macruby hello_world.rb

Try clicking the button and you should see something like this in the console:

1
2009-07-31 23:58:11.752 macruby[28261:10b] Hello World

Well, that’s nice and all, but I want something more

Once you start building anything serious, a single file app isn’t really viable. Fortunally though, HotCocoa comes with a generator:

1
$ hotcocoa my_app

This will create a directory structure for you, with some rake tasks and a skeleton app. You can try it out like this:

1
2
$ cd my_app
$ macrake

Where to go from here?

Both MacRuby and HotCocoa are pretty young and so documentation is sparse, there are however a couple of really good examples under: /Developer/Examples/Ruby/MacRuby/ and /Developer/Examples/Ruby/MacRuby/HotCocoa

Posted in Programming, Ruby at July 31st, 2009. No Comments
Tagged with , . Written by: Patrik Hedman

pastbedti.me is using WP-Gravatar