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

My Sinatra + Apache + Passenger setup did not just run :)

Deploying a simple Sinatra rack application under Apache and Phusion Passenger turned out not work out of the box for me.

I already had a virtual host so I decided to deploy with passengers sub URI (sub URI documentation).

To make this work you’ll need Apache installed with Phusion Passenger setup (Passenger installation)

This is what I started with

This is my folders for the already existing website.

1
2
3
4
# Existing homedir
/home/my_web/
# Current webroot
/home/my_web/htdocs

Creating folders and files for Sinatra

The first thing you want to do is to create folders and files for Sinatra.

1
mkdir /home/my_web/sinatra
1
2
3
4
5
6
cd /home/my_web/sinatra
mkdir tmp
mkdir logs
mkdir public
touch app.rb
touch config.ru

Create symlink

Create a symbolic link from our current webroot to the new Sinatra app so that apache/passenger can find it.

1
ln -s /home/my_web/sinatra/public /home/my_web/htdocs/app

Creating the application

We also need a Sinatra application for this to work so lets fill those files.

File: config.ru

1
2
3
4
5
6
7
8
9
10
11
require 'app'

set :environment, ENV['RACK_ENV'].to_sym
set :app_file,     'app.rb'
disable :run

log = File.new("logs/sinatra.log", "a")
STDOUT.reopen(log)
STDERR.reopen(log)

run Sinatra::Application

File: app.rb

1
2
3
4
5
6
7
8
9
10
11
require 'rubygems'
require 'sinatra'

before do
  # Strip the last / from the path
  request.env['PATH_INFO'].gsub!(/\/$/, '')
end

get '' do
   "Hello world"
end

Apache configuration

Now we need to setup apache so that it can find our Sinatra app and load it.

The only thing you need to do is add the following line to your existing VirtualHost block:

1
RackBaseURI /app

This line will tell passenger to look into our existing webroot for a symlink thats named app and which points to our rack app. (RackBaseURI documentation)

Virtual host entry

1
2
3
4
5
6
7
8
9
10
11
12
<VirtualHost *:80>
  ServerName www.example.com
  ServerAlias example.com
  DocumentRoot /home/my_web/htdocs/
  RackBaseURI /app

  <Directory "/home/my_web/htdocs/">
    Order allow,deny
    Allow from all
    AllowOverride All
  </Directory>
</VirtualHost>

The best part is that you are allowed to specify this option multiple times. So you can easily setup multiple apps under the same virtual host.

Cheers!

Posted in Hosting, Programming, Sinatra at November 30th, 2009. No Comments
Tagged with , , , , , , . Written by: Mathias Stjernström

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

Recently I’ve been working a lot with dates and tonight I had a hard time finding information about how to group a model by date when the model only have a timestamp column.

Lets pretend we have a user model with a created_at attribute which is stored as a timestamp.

If we want to plot a simple graph showing signups per date this is the way to extract them:

1
User.count(:group => "DATE(created_at)")

Thats all there is to it. From this you will get an OrderedHash containing the date and count of users for each date.

One small thing to remember if you are using PostgreSQL. You will need the DATE() function in any ORDER/SELECT statements because PostgreSQL will only select/order by fields thats in the GROUP BY statement and this is a pretty healthy behavior that many databases (no names here) don’t care about. Think about it. If you are grouping all users by date and use * as selector how would the database know which username or email address to display?

This is what happens if you try to group by created_at without DATE() ->

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
>> User.count(:order => 'created_at DESC', :group => ["DATE(created_at)"])                                                
ActiveRecord::StatementInvalid: PGError: ERROR:  column "users.created_at" must appear in the GROUP BY clause or be used in an aggregate function
: SELECT count(*) AS count_all, DATE(created_at) AS date_created_at FROM "users"  GROUP BY DATE(created_at)  ORDER BY created_at DESC
        from /tmp/app/vendor/rails/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb:212:in `log'
        from /tmp/app/vendor/rails/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb:507:in `
execute'
        from /tmp/app/vendor/rails/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb:985:in `select_raw'

        from /tmp/app/vendor/rails/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb:972:in `select'
        from /tmp/app/vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb:7:in `
select_all_without_query_cache'
        from /tmp/app/vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb:62:in `select_all'

        from /tmp/app/vendor/rails/activerecord/lib/active_record/calculations.rb:255:in `execute_grouped_calculation'
        from /tmp/app/vendor/rails/activerecord/lib/active_record/calculations.rb:132:in `
calculate'
        from /tmp/app/vendor/rails/activerecord/lib/active_record/calculations.rb:130:in `catch'

        from /tmp/app/vendor/rails/activerecord/lib/active_record/calculations.rb:130:in `calculate'
        from /tmp/app/vendor/rails/activerecord/lib/active_record/calculations.rb:48:in `
count'
        from (irb):18

And this is the right way to do it:

1
2
>> User.count(:order => 'DATE(created_at) DESC', :group => ["DATE(created_at)"])
=> #<OrderedHash {"2009-10-14"=>22, "2009-10-25"=>4, "2009-11-04"=>8, "2009-10-15"=>9, "2009-10-26"=>16, "2009-11-05"=>9, "2009-10-16"=>193, "2009-10-27"=>14, "2009-11-06"=>9, "2009-10-17"=>49, "2009-10-28"=>15, "2009-11-07"=>6, "2009-10-18"=>36, "2009-10-29"=>8, "2009-10-19"=>116, "2009-10-30"=>15>

As you may notice the Hash does not look ordered. But if you loop over it you will get them in order:

1
2
3
4
5
6
7
8
9
10
11
12
>> User.count(:order => 'DATE(created_at) DESC', :group => ["DATE(created_at)"]).each {|u| puts "#{u[0]} -> #{u[1]}" }
2009-11-07 -> 6
2009-11-06 -> 9
2009-11-05 -> 9
2009-11-04 -> 8
2009-11-03 -> 14
2009-11-02 -> 20
2009-11-01 -> 10
2009-10-31 -> 6
2009-10-30 -> 15
2009-10-29 -> 8
..

And thats how you group a timestamp field with just its date part.

Cheers!

Posted in Databases, PostgreSQL, Rails, Ruby at November 8th, 2009. No Comments
Tagged with , , , , . Written by: Mathias Stjernström

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

A couple of days ago my Terminal.app (console) got a really annoying feature. When launching the console or when I created a new tab it got stuck for about 5-10 seconds before I got my prompt.

If you are like me and are spending most of your time in Terminal.app you understand how annoying this is/was.

I tried to rename .profile, .inputrc and evey other startup script I had in my home folder but the problem did not go away.

Then I found an OSX user which had his Terminal crash when started. He solved his problem by cleaning up some OSX systemlogs. So I thought I try the same trick.

The logfiles which he removed where the asl files under /private/var/log/asl/

I read about them here: http://macosx.com/tech-support/can-i-deleteasl-log/24223.html

But I figured I’d just remove them all :)

1
sudo rm -rf /private/var/log/asl/*

When all asl files where removed my Terminal went back to normal again and I am sooooooo relieved.

This worked for me BUT I do not recommend you to remove anything if you do not know what you are doing!!!

Cheers!

Posted in Operatingsystem, Utilities at September 11th, 2009. 2 Comments
Tagged with , , , , . Written by: Mathias Stjernström

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

pastbedti.me is using WP-Gravatar

pastbedti.me is Digg proof thanks to caching by WP Super Cache!