En ce moment, je regarde beaucoup comment fonctionne Shopify. A défaut d’avoir une boutique sur laquelle faire quelques tests, je regarde les divers outils extraits de l’application et dont le code a été ouvert. Vous pouvez en voir la liste sur github.
Aujourd’hui je voudrais vous parler de l’un de ceux-ci, Liquid.

Utilisé par Shopify pour mettre en place un système de templating sécurisé, n’autorisant pas l’exécution de code ruby, l’outil est assez impressionnant de par son utilisation.
Les habitués de Django naviguent en terrain connu. Mais c’est bien du Ruby.

<ul id="products">
    {% for product in products %}
        <li>
            <h2>{{product.title}}</h2>
            Only {{product.price | format_as_money }}
            <p>{{product.description | prettyprint | truncate: 200  }}</p>
        </li>
    {% endfor %}
</ul>

Comme vous pouvez le constater, nous pouvons parcourir des éléments et en afficher les valeurs sans problème.
Pour une documentation détaillée de Liquid, je vous invite à voir la documentation de Shopify.

Quant à la définition côté code, ce n’est pas beaucoup plus compliqué.

Liquid::Template.parse(read_template).render 'products' => Product.find(:all)

Et si vous avez une application Rails (comme je suppose que c’est le cas), c’est d’autant plus simple. Il suffit de redéfinir le « handler » de vue par celui de Liquid.
Dans votre fichier config/environment.rb, ajoutez le snipper suivant :

ActionView::Base::register_template_handler :liquid, LiquidView

Auquel cas vous n’avez pas à parser vous même le contenu (Liquid::Template.parse est inutile). C’est fait automatiquement avec les variables que vous avez défini.
Tous vos templates utiliseront ainsi Liquid. Les tags <% ne seront plus valides.
Attention cependant ne commencez pas à intégrer Liquid dans toutes vos applications rails en vous disant que cela sera plus fun. Liquid est très sympa lorsque le code de vos templates est susceptible d’être modifié par un utilisateur tiers. Cependant votre application y perdra inévitablement en rapidité.

Bien évidemment si vous avez besoin de Liquid, cela signifie que vos utilisateurs peuvent modifier les vues rendues par votre application.
Dans ce cas je vous conseille fortement l’utilisation de theme support afin de gérer ceux-ci.
Son utilisation est également particulièrement simple.

Au lieu d’avoir directement vos vues et fichier publiques dans le répertoire views, aurez un répertoire « themes » contenant chacun de ces thèmes et ses vues ainsi que les fichiers publics.

$app_root
    themes/
        [theme_name]
            images/
            stylesheets/
            javascripts/
            views/
                layouts/

Et dans votre contrôleur, vous pouvez aisément choisir un thème ou un autre.

class ApplicationController < ActionController::Base
    layout 'application'
    theme 'mon_theme'
end

Voir même définir -comme vous pouvez le faire avec le layout- celui-ci grâce à une méthode.

class ApplicationController < ActionController::Base
    layout 'application'

    theme :get_theme
    def get_theme
        current_user.theme
    end
  end

Ainsi chacun de vos utilisateur peut lui même choisir le thème qu’il désire pour votre application.

Comme vous le savez déjà, je suis actuellement en pleine phase de lancement comme entrepreneur.
Lorsque je parle de cela à mes amis « IRL » qui, pour la plupart, ne sont absolument pas familiers avec le monde du web (excepté pour Facebook, MSN etc), j’ai toujours des remarques du genre « ouah ! Tu vas être trop riche ! »
J’ai même une amie qui, pas plus tard que dimanche dernier, a élaboré tout un stratagème ayant pour but de m’épouser maintenant, attendre que je sois milliardaire et me tuer pour empocher le pactole.

Et ce matin je vois un article de Matt Linderman sur le blog 37signals intitulé ‘‘I quit my job’ applause‘.
A ce propos, je vous recommande fortement la lecture du blog 37signals. C’est particulièrement enrichissant.

Voici une traduction libre de cet article :

[En questions à une conférence] Plusieurs personnes dirent : « J’ai été tellement inspiré par ce que vous avez dit que j’ai décidé de quitter mon boulot et de démarrer un nouveau business ! » Et alors la salle entière se met à applaudir.

Puis :

Mon problème avec ceci : quitter votre boulot est facile. Cela ne mérite pas d’applaudissements. Si vous démissionnez, que vous démarrez quelque chose de nouveau et le faites durer alors vous méritez d’être applaudis. Mais uniquement démissionner ? N’importe qui peut faire cela.

Et démarrer quelque chose n’est pas le plus difficile. C’est même facile de démarrer. Continuer est le plus dur. Regardez simplement le nombre de blogs abandonnés sur le web pour obtenir une preuve de cela.

Tout cela pour dire que pour beaucoup, lorsque l’on démarre en tant qu’entrepreneur, c’est quelque chose d’énorme et on va forcément réussir. Ce n’est pas forcément le cas (même si c’est toujours ce que l’on souhaite).
Ce qui est important (et difficile), c’est de réussir une fois que l’on a commencé. Pas juste de commencer.

Je sors beaucoup de chez moi en octobre. Petit résumé :

  • Je serai à Paris Web les 8, 9 & 10 octobre 2009. Et j’animerai un atelier le samedi sur le thème Test automatisé d’applications JavaScript avec Qunit et Selenium.
    Par ailleurs si vous êtes parisien et éditeur dmoz, un repas s’organise le samedi soir ou dimanche midi. Signalez vous sur le forum.
  • Je serai aux JDLL le 16 octobre pour animer une conférence sur le thème Dmoz : une autre manière de chercher sur le web. Rendez-vous ce vendredi là de 17h à 17h55.
  • Je serai au SEOCamp le 17 octobre (mais j’ai une autre soirée qui se superpose. Donc je serai probablement en retard).
  • Comme déjà dit, je suis maintenant auto entrepreneur.
    A partir du 1er octobre, je ne travaillerai plus pour O2Sources les vendredi.

Un programme assez chargé donc. Signalez-le moi si on est susceptible de se voir quelque part :)

Un peu à la suite de mon voyage en Israel et Palestine de cette été, j’ai été invité samedi matin à l’une des sessions du forum Libération.

Animée par Philippe BARBARIN, cardinal de l’Eglise romaine catholique et archevêque de Lyon (avec qui je suis parti en Terre Sainte cette été d’ailleurs) ainsi que Tadeusz MAZOWIECKI, premier ministre Polonais de 1989 à 1990 (donc au moment même de la chute du mur de Berlin et du communisme).
Sur la question « Faut-il oublier ou pardonner ? ». Un sujet particulièrement intéressant avec deux intervenants tout aussi intéressant l’un que l’autre de par leur position passée et présente.

Malheureusement Libération ne permet pas l’inclusion d’une vidéo en particulier sur une page. Je ne peux donc vous la fournir dans cette article.
Mais vous pouvez la visualiser sur le site du forum Libération.

Et on me vois même à quelques reprises particulièrement bien puisque l’amie avec qui j’étais pose une question et que je suis assis à côté d’elle.

Le service de raccourcissement d’url tr.im vient de rendre public le code de son application.
Je ne critique pas l’idée qui est particulièrement bonne. C’est cool :)

Mais pas dans la manière dont la chose est développée et qui serait presque un cas d’école.
Si on se rends à la base du projet, on vois trois applications Rails :

  • trim
  • trim_api
  • trim_redirect

Et en comparant trim et trim_api, on se rends compte que les deux applications sont identiques, à l’exception près que l’une retourne de l’HTML et l’autre du XML.
Urk donc. Une répétition de code particulièrement flagrante et strictement inutile.
Si, avec Rails, vous désirez retourner deux pages différentes pour le même code, une en HTML et l’autre en XML (ou tout autre format), il suffit d’utiliser respond_to.
Nous avons donc déjà une application que l’on peut fusionner avec la principale.

Quant à la troisième, qui gère les redirections, elle est nettement fusionnable à l’application principale. Il s’agit simplement d’une route par défaut.
Un petit :

map.connect ':redirect_id', :controller => 'redirect', :action => 'index'

Avec le code déjà présent dans le contrôleur redirect pour que cela fonctionne très bien.
Cette troisième application est donc également inutile. Nous avons trois applications différentes en une, et deux d’entre elles sont inutiles. Pas cool.

Enfin regardons trois dossiers similaires : les tests.
Le premier (qui est censé être le plus important vu que c’est le site) n’a strictement aucun test.
L’API a quelques tests. Je n’ai pas passé de rcov dessus cependant. Et vu leur nombre, je doute que l’on ait un pourcentage de code testé convenable.
Quand aux redirections, c’est pas testé non plus.

Alors oui, mettre ses applications en open source c’est cool.
Mais le minimum est d’éviter ce genre d’erreur de débutant (je parle surtout de la première. Le manque de tests, vu le peu de développeurs qui en font encore aujourd’hui, c’est pas spécialement étonnant) est un strict minimum.
D’ailleurs j’ai également ouvert une issue sur le projet.
Et vous vous en pensez quoi ?

Désolé j’ai dit dans mon précédent article que je ne reparlerai pas de GIT cette semaine.
Mais je tiens à partager ma découverte du jour que je trouve particulièrement cool :)

Il peut être particulièrement utile de, par exemple, recevoir un email à chaque fois que l’un des développeurs de votre application fait un push sur le repository distant.
Ou encore vous pouvez désirer exécuter automatiquement les tests de votre application avant chaque commit et n’autoriser le commit que si tous passent.
Et automatiser ce genre de choses pourrait être particulièrement kiffant.

Du coup … haaaave you met GIT Hooks ?
Dans le répertoire .git/hooks de votre application existent plusieurs fichiers .sample. Chacun représente un hook et est exécuté au moment opportun.
Par exemple « post-receive » sera exécuté du côté du repository distant à chaque fois que quelqu’un poussera le projet :)
De même « pre-commit » sera exécuté du côté du client avant chaque commit (et vous pourrez décider de refuser le commit automatiquement).

Par exemple plaçons dans notre fichier « post-receive.sample » que nous commencons par renommer en y enlevant l’extension « .sample » afin qu’il se nomme « post-receive » (il doit également être exécutable).

/home/ruby/scripts/post-receive.rb $1 $2 $3

Le script /home/ruby/scripts/post-receive.rb sera exécuté automatiquement à chaque post receive.
Et dans ce script nous plaçons un envoi de mail :

require 'net/smtp'
msg = "Subject: A push has been made\r\n\r\nA push has been made on one of your repositories.\r\nOld commit: " + ARGV[0] + "\r\nNew commit: " + ARGV[1] + "Ref: " + ARGV[2]
Net::SMTP.start('localhost') do |smtp|
    smtp.send_message msg, 'noreply@localhost', 'you@your_email.com'
end

Ainsi à chaque push fait, nous envoyons un email à l’adresse de notre choix (you@your_email.com) signalant qu’un nouveau push a été fait.
Cela peut être une liste de diffusion par exemple.
Mais bien évidemment cela peut être autre chose qu’un email. Il est tout à fait possible, par exemple, de signaler cela sur un salon Campfire utilisé par l’équipe de développement.

Note : si vous hébergez votre repository sur GitHub, il ne vous est pas utile de créer de hook post-receive de cette manière.
Ceux-ci sont gérés via l’interface web.

Pour quelques informations supplémentaires et notamment l’exécution automatique des tests avant un commit que j’ai mentionné plus haut, je vous invite à lire Les hooks sur le Git Book (fr).

Rassurez vous ceci est le dernier article de cette série sur GIT. Je pense repartir sur un peu de rails la semaine prochaine.
On me pose souvent la question « pourquoi choisir GIT et pas SVN ? »

Voici donc de manière absolument pas triée ni objective tous les arguments qui font que je préfère GIT à SVN (et de loin).
Notez que ce n’est que mon opinion. Vous pouvez en avoir une autre c’est absolument pas génant.

  • Pouvoir être nomade

    C’est ce que je montre dans mon article précédent.
    Avec GIT, contrairement à SVN, vous pouvez continuer à committer et ainsi conserver un repository avec des commits propres et pas un gros commit une fois de temps en temps. Même si vous n’êtes pas connecté ou n’avez pas accès à votre repository distant. Vous restez productif même en déplacement.

  • Une vraie gestion des tags et branches

    Avec SVN si vous désirez créer une nouvelle branche c’est pas compliqué : vous faites un copier/coller de votre répertoire trunk, le mettez dans branch/nom_de_la_branche. Et c’est fait. Y’a plus qu’à committer. Et le jour ou vous voulez fusionner les deux branches, morflez.
    Pareil pour les tags.

    GIT gère les branches et tags de manière native.
    Pas besoin d’action manuelle (copier/coller).
    Vous faites un « git branch <nouvelle_branch> » et votre branche est créée.
    Un « git checkout <branch> » et vous changez de branche active.
    Et un « git rebase <branch> <seconde_branch> » et vos deux branches sont fusionnées !

  • GitHub

    Ouais c’est pas vraiment GIT.
    Mais je kiffe littéralement GitHub.
    Pouvoir forker un projet en un clic; pouvoir commenter des commits etc.
    Tout projet libre devrait permettre ce genre de choses sur son repository. C’est ça qui pousse les autres développeurs à créer des patchs.

Ces trois arguments me suffisent personnellement à nettement préférer GIT à SVN.
Et vous ? Quel est votre logiciel de contrôle de version préféré ?

Je viens de réaliser un screencast sur GIT et la synchronisation multi repositories.
Celui-ci explique :

  • Comment transmettre les données committées sur votre serveur de développement
  • Comment les transmettre sur un système de fichier local (par exemple une clé USB) lorsque vous êtes en hors ligne
  • Comment récupérer les derniers commits distants

Vous pouvez visualiser ce screencast ci-dessous.

Lorsque vous manipulez un repository GIT en utilisant (voir en abusant (ce qui n’est pas forcément négatif)) les branches, vous pouvez régulièrement vous poser la question « dans quelle branche suis-je ? Est-ce la bonne ? »
Et c’est toujours particulièrement lourd de devoir faire un
git branch

Afin de voir toutes les branches et de trouver l’active.
Je viens cependant de tomber sur une astuce donnée par le support github.

# git branch
parse_git_branch() {
    git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/(\1) /'
}
PS1="\$(parse_git_branch)$PS1"

Placez ceci dans ~/.bashrc ou /etc/bashrc (pour que cela soit valide pour tous les utilisateurs de la machine).
Rechargez votre console et admirez :)

dmathieu@dmathieu-ubuntu:~$ cd /home/dmathieu/projects/refstats/
(master) dmathieu@dmathieu-ubuntu:~/projects/refstats$

Lorsque vous êtes dans un repository GIT, la branche courante s’affichera.
Dans le cas contraire, rien ne s’affichera :)

Certaines personnes, notamment Clément (et d’autres) m’ont demandé il y a quelques semaines de cela de rédiger un article sur les commandes GIT de base pour une utilisation console.
Déjà, sachez qu’il existe de multiples interfaces graphiques pour Windows et Mac.
Il en existe également pour Linux. Mais je n’ai rien trouvé qui ne convienne à mes exigences. Donc je fais tout en ligne de commande et j’utilise gitk pour visualiser les commits faits et en cours.
Je n’aborde ici que les commandes de base, pour le développement de tous les jours. Pas de notion de branches ou de tags donc.

A chacune des commandes ci-dessous, il faut précéder l’exécutable « git ». Nous aurons donc : git <nom de commande>

  • add

    Permet d’ajouter des fichiers au prochain commit. Cette commande prends comme paramètre le nom du fichier ou du répertoire à ajouter.
    Exemples :

    git add app/models/mon_model.rb

    Ajoutera le fichier app/models/mon_model.rb à la liste des fichiers à committer.

    git add app/models

    Ajoutera tous les fichiers présents dans le dossier app/models dans la liste des fichiers à committer

    git add .

    Ajoutera tous les fichiers du projet à committer.
    Evidemment seuls les nouveaux fichiers ou ceux modifiés seront ajoutés. C’est le principe même d’un SCM ;)

  • rm

    Vous l’aurez peut-être deviné, cette commande est l’inverse de add. Elle vous permet de supprimer un fichier du repository.
    En effet un fichier supprimé physiquement n’est pas supprimé dans le repository. Il faut donc le faire via ce rm.
    Note : si vous supprimer un fichier existant avec cette méthode, il sera supprimé physiquement.

    Exemples :

    git rm app/models/mon_model.rb

    Supprimera le fichier app/models/mon_model.rb

    git rm -r app/models

    Supprimera tous les modèles du projet.
    Notez le -r qui force la récursivité car vous supprimez un répertoire.

  • commit

    Après avoir ajouté et supprimé tout plein de fichiers à notre prochain commit, il faut faire celui-ci !
    La commande commit permet donc de valider les changements faits. Tant que vous n’avez pas committé, vous pouvez revenir en arrière (même après en fait. Mais on verra pas cela dans cet article).

    Exemple :

    git commit -m "Un super message de description"
  • reset

    Comme je disais, tant que vous n’avez pas committé, vous pouvez annuler des changements particulièrement simplement avec git reset.
    Cette commande réinitialise tous les fichiers dans votre repository à leur état lors du dernier commit. Vous annulez donc tous les changements non committés et revenez sur une base propre.

    Exemple :

    git reset --hard HEAD
  • push

    Après avoir committé vos changements, il vous faut probablement pousser ceux-ci sur le repository distant afin de pouvoir partager vos modifications avec les autres développeurs du projet.
    Ou bien tout simplement de pouvoir récupérer ces changements sur une autre machine (celle de test ou de production par exemple).

    Exemples :

    git push

    Poussera la branche courante sur le repository distant nommé « origin »

    git push backup

    Poussera la branche courante sur le repository distant nommé « backup »

    git push backup V2

    Poussera la branche nommée « V2″ sur le repository distant nommé « backup ».

  • pull

    Pousser c’est bien. Mais il faut récupérer les données qui ont été poussées par vous sur une autre machine ou par un autre développeur.
    Cette commande fonctionne avec exactement les même arguments que la précédente mais pour récupérer les données de votre repository.

Voila. Avec tout cela, vous pouvez :

  • Ajouter, supprimer des fichiers et les committer
  • Annuler une modification non committée
  • Envoyer et récupérer les données sur un repository distant

Ce qui est, au final, les commandes GIT de tous les jours (dans l’utilisation que j’en fais du moins).
Peut-être ferais-je d’autres articles plus avancés au niveau de la gestion des branches ou de l’annulation d’un commit. Mais cela viendra dans un prochain article.

 
Fork me on GitHub