Créer son moteur de recherche avec Ruby et Xapian

SoapUI-3.5-beta1.app

Ruby Timer

Create a Web App with Node.js

Node.js is the new hype for server-side webish things. It's evented, non-blocking, fast and in javascript (not another language to learn, yay!). Real-Time Web is around the corner.

Javascript means you can use existing JS librairies. In this example I will use Mustache.js and Underscore to create the core of a minimal web application.

Let's begin

I have 4 files: main.js, mustache.js, underscore.js, templates/index.html

We will put our code in main.js. First we require the things we'll need:

var sys = require('sys'), http = require('http'), posix = require('posix')
require('./underscore')
var Mustache = require('./mustache')

Note that Underscore is CommonJS compliant so you don't have to do anything for it. Then we add our actions which are composed by 3 things: URI, template name and the view.

var actions = [];

actions.push({
  path: "/",
  template: "index.html",
  view: {
    title: "Joe",
    calc: function() { return 2 + 4; }
  }
})

We can create as many actions as we want. Now let's create the server:

http.createServer(function (req, res) {}).listen(8000);

The server will be running but will not know how not handle actions. Let's add a request listener:

http.createServer(function (req, res) {
  req.addListener('complete', function() {})
}).listen(8000);

The req variable contains the URI, so we will select the action corresponding to the request:

http.createServer(function (req, res) {
  req.addListener('complete', function() {
    var action = _(actions).chain().select(function(a) { return req.uri.path == a.path }).first().value()
  })
}).listen(8000);

If the request doesn't match an action, we will send an error:

http.createServer(function (req, res) {
  req.addListener('complete', function() {
    var action = _(actions).chain().select(function(a) { return req.uri.path == a.path }).first().value()

    if (_.isEmpty(action)) {
      res.sendHeader(404, {'Content-Type': 'text/plain'})
      res.sendBody("Error")
      res.finish()
    } else {}
  })
}).listen(8000);

In the other case we render the action:

http.createServer(function (req, res) {
  req.addListener('complete', function() {
    var action = _(actions).chain().select(function(a) { return req.uri.path == a.path }).first().value()

    if (_.isEmpty(action)) {
      res.sendHeader(404, {'Content-Type': 'text/plain'})
      res.sendBody("Error")
      res.finish()
    } else {
      posix.cat("./templates/" + action.template).addCallback(function(template) {
        res.sendHeader(200, {'Content-Type': 'text/html'})
        res.sendBody(Mustache.to_html(template, action.view))
        res.finish()
      })
    }
  })
}).listen(8000);

We get the template content then renders it when the I/O process is complete. Here's the template:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
  <title>My Framework</title>
</head>

<body>
  {{title}} spends {{calc}}
</body>
</html>

And that's all! It's running and you can create your blog with it for example.

There's already a lot of Node.js frameworks that you can find on GitHub if you search for "node". But there's nothing really mature at this time.

Update (10 Feb 2010)

I forgot to mention that the mustache.js I've used was tweaked. We just have to add this following code at the end of the mustache.js file:

for (var name in Mustache)
    if (Object.prototype.hasOwnProperty.call(Mustache, name))
        exports[name] = Mustache[name];

This will be merge into the main library in the near future and you can find the whole file here

Create a Web App with Node.js

Node.js is the new hype for server-side webish things. It’s evented, non-blocking, fast and in javascript (not another language to learn, yay!). Real-Time Web is around the corner.

Javascript means you can use existing JS librairies. In this example I will use Mustache.js and Underscore to create the core of a minimal web application.

Let’s begin

I have 4 files: main.js, mustache.js, underscore.js, templates/index.html

We will put our code in main.js. First we require the things we’ll need:

Note that Underscore is CommonJS compliant so you don’t have to do anything for it. Then we add our actions which are composed by 3 things: URI, template name and the view.

We can create as many actions as we want. Now let’s create the server:

The server will be running but will not know how not handle actions. Let’s add a request listener:

The req variable contains the URI, so we will select the action corresponding to the request:

If the request doesn’t match an action, we will send an error:

In the other case we render the action:

We get the template content then renders it when the I/O process is complete. Here’s the template:

And that’s all! It’s running and you can create your blog with it for example.

There’s already a lot of Node.js frameworks that you can find on GitHub if you search for “node”. But there’s nothing really mature at this time.

Update (10 Feb 2010)

I forgot to mention that the mustache.js I’ve used was tweaked. We just have to add this following code at the end of the mustache.js file:

This will be merge into the main library in the near future and you can find the whole file here

Sortie de Typo 5.4.0

Ça y est, une nouvelle version de Typo est lancée dans la nature. Je n'ai hélas que très peu participé à cette nouvelle version faute de motivation/temps. Mais je suis toujours très content de voir une nouvelle version de ce blog sortir.

A chaque release, une nouvelle admin fait son apparition, mais à chaque fois elle est meilleure que la précédente, donc c'est une excellente chose.

J'ai bien-sûr mis à jour ce blog et j'ai aussi switché sur le nouveau thème par défaut. Je suis toujours aussi nul en design.

En petit cadeau, voici mon fichier capistrano que j'utilise pour déployer ce blog. Ça peux toujours vous servir. On ne sait jamais.

set :application, "typo"
set :repository,  "git://github.com/fdv/typo.git"
set :domain, "blog.shingara.fr"

# If you aren't deploying to /u/apps/#{application} on the target
# # servers (which is the default), you can specify the actual location
# # via the :deploy_to variable:
set :deploy_to, "/var/rails/blog-typo"
#
# # If you aren't using Subversion to manage your source code, specify
# # your SCM below:
set :scm, :git

set :runner, "rails"
set :user, "rails"
set :use_sudo, false

set :thin_conf, "/etc/thin/#{domain}.yml"

role :app, domain
role :web, domain
role :db,  domain, :primary => true

task :update_config, :roles => [:app] do
  run "cp -Rf #{shared_path}/config/* #{release_path}/config/"
  run "ln -s #{shared_path}/files #{release_path}/public/files"
end

task :update_gems, :roles => [:app] do
  run "cd #{release_path} && RAILS_ENV=production rake gems:install"
end


after "deploy:update_code", :update_config
after "deploy:update_code", :update_gems


namespace :deploy do
  task :start, :roles => [:app] do
    run "thin -C #{thin_conf} start"
  end

  task :stop, :roles => [:app] do
    run "thin -C #{thin_conf} stop"
  end

  task :restart, :roles => [:app] do
    run "thin -C #{thin_conf} restart"
  end
end

task :clear_cache, :roles => [:app] do
  run "cd #{current_path} && RAILS_ENV=production rake sweep_cache"
  run "cd #{current_path} && RAILS_ENV=production rake tmp:cache:clear"
end

after "deploy:restart", :clear_cache
after "deploy:start", :clear_cache

English Translation

Valider un modèle qui ne descend pas de ActiveRecord::Base sans plugin

Bye bye TextMate, Bonjour Coda

Bookmarks #2

The rest of my bookmarks. I finally finish to read all my tech & design bookmarks, yay!

Ruby

Javascript

HTML & CSS

Design

iPhone

Bookmarks #2

The rest of my bookmarks. I finally finish to read all my tech & design bookmarks, yay!

Ruby

Javascript

HTML & CSS

Design

iPhone