When you get user information in console, you might, sometimes, need to get sensible information. Password for example.
Which can’t be displayed on the screen for security reasons.
The library Ruby Password allows you to do that quite easily.
However it implies you depend on this library. And that’s something I don’t wish. Particularly for something so simple.

The solution I’m suggesting here uses the linux features (not tested on windows. But who’s still using it today ? :mrgreen: ).

begin
    print "Username: "
    username = $stdin.gets.chomp

    print "Password: "
    # We hide the entered characters before to ask for the password
    system "stty -echo"
    password = $stdin.gets.chomp
    system "stty echo"
rescue NoMethodError, Interrupt
    # When the process is exited, we display the characters again
    # And we exit
    system "stty echo"
    exit
end

What are we doing ?
We start by asking the user’s nickname.

print "Username: "
username = $stdin.gets.chomp

This is not a sensible data and can be displayed. Nothing specific to do.

Then we ask for a password. Here we must hide it.

print "Password: "
system "stty -echo"
password = $stdin.gets.chomp
system "stty echo"

The « stty -echo » will hide every character that should be displayed on the console.
The « stty echo » displays them again.

Until there is works. Cool !
But somehowe we have a boring user, whom decides at the last moment to enter Ctrl-C to quit the program and finds himself in console with the -echo mode and doesn’t see what he enters in. We’ve just lost a friend.

Fortunately we have exceptions notifications and we already detect an Interrupt to exit the program cleanly.
Then we just have to display the characters again when there’s this interrupt :)

begin
    # ...
rescue NoMethodError, Interrupt
    system "stty echo"
    exit
end

Hop ! :)
And the project that uses this is glynn :)

Si j’étais marseillais un verre de ricard à la main, je me serai posé cette question bien plus tôt !
Mais ce n’est pas le cas. Heureusement il n’est jamais trop tard ! ;)

Par habitude, afin de mettre à jour un repository GIT distant, j’utilise git pull.
Ca fonctionne à merveille, tout le monde a ses données à jour et on se croirait presque au pays des bisounours.
Mais Gargamel vient mettre son nez là-dedans (ouais je mélange Schtroumpf et Bisounours. Honte sur moi !).

Ce matin, j’ai voulu, avant de faire la release de la version 1.0.0 de jesus (car il est prêt pour la production), mettre à jour la documentation.
Le principe est simple. J’utilise GitHub Pages. Il me faut donc juste une branche « gh-pages », dont le contenu correspond à ce qui est en ligne chez GitHub pour ma documentation.
Dès que je commit sur cette branche, la page en ligne est mise à jour.

Cependant mes deux branches master et gh-pages n’ont pas le même index. Les deux ne peuvent pas être mergées !
Ce matin, je me vois donc faire un

git pull origin gh-pages:gh-pages

En me disant « comme cela, je récupère le contenu de la branche de documentation ».
Et la je me retrouve avec une dizaine d’erreurs de conflit ! WTF comme dirait l’autre.

Et justement pour le coup, j’aurai du faire un

git fetch origin gh-pages:gh-pages

La différence entre ces deux commandes en apparence similaires est pourtant énorme.
Git fetch ne fait que récupérer les données. Git pull les récupère et fait un merge avec la branche courante …
Du coup merge mes deux branches, vu qu’elles ont pas la même base, c’est pas super cool.

Moralité : vous pouvez faire un git fetch afin de mettre à jour votre copie locale avec les derniers commits distants. La branche sur laquelle vous faites le fetch aura les derniers commits.
Mais votre branche de travail ne sera pas modifiée.
Si vous faites un git pull, non seulement la branche sur laquelle vous faites le fetch aura les derniers commits distants. Mais votre branche de travail sera également mergée avec ces derniers commits.

En y réflechissant bien, fetch est bien plus recommandable que pull, qui peut casser un repository assez facilement.

I love Git and GitHub. All my open source projects are hosted there (even though there isn’t a lot of them).
However I see one huge problem with it. Let me explain !

Today I falled on fetcher. One project that I was following since a few months.
But I forgot it and was happy to find it again and to think « great library. Let’s try it ».
So I take a look at the documentation and I see … It’s only a rails plugin. Not cool. I don’t want to parse emails on an IMAP server with Rails.
I want to do that in console and add the mails in a database.

So I think « let’s fork the project and make it a gem ». But as I don’t have a lot of time, I say : « what if someone else already did that before ? »
Then I look at the project’s network. And I see several other forks, two of them having already ported the library to a gem.

And here is the problem. The original project doesn’t seem to be maintained anymore. Other people have submited several patches to it.
But nothing takes all those patches to do one single and great project. And that’s a problem that appears on several other projects.

For some professional reasons, I’m currently taking a deeper look at CouchDB.
And particularly CouchREST. And here comes the nightmare !
There’s not one, not two but three active repositories for the project.mattetti’s, jchris’ and couchrest’s.
The original one is jchris. The other two ones are forks.
But apparently, the two ones are development versions (the forks of the two main developers ?). And the third one is the stable integration.
Cool, but not readaly at all.

I’d see two solutions for these two problems with GitHub.
For the couchrest problem, please projects owners, update your project description to explain what this repository is about.
Say this is only a development branch. Or it’s the stable branch and we should clone it and not your unstable testing repo.

For the fetcher problem, it seems to me to more like an architectural problem on GitHub.
Being able to move an original project from one place to an other (say « this project isn’t a fork. But this one is ») would change a lot of things.
We could, with the owner’s consent (or the github’s staff approval if the owner is unreachable) change the original project repository to some other place.
That’s called communication. If you see a project, you go to the original one, to download it and not a fork that might break everything.
But when it’s not the original that you must use but one specific fork, you’re not Mrs Irma and you can’t guess which one to use magically :)

Yes, this is a hidden message to defunkt, mojombo, tekkub, kneath or any other GitHub staff member if you read me.

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.

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).

Simian, aka Similarity Analyser est un outil des plus merveilleux. Il analysera vos lignes de code et détectera des potentielles répétitions.

A cela, nous couplons un gem de Jean-Michel Garnier (qui était présent au RubyCamp Lyonnais), Don’t Repeat Yourself.
Et à partir de maintenant, nous pouvons tester que nos applications Ruby et Rails sont DRY !!
J’ai testé et ça fonctionne plutôt du tonnerre.

Installation du plugin :
Si vous n’avez pas encore le catalogue de gems de GitHub, ajoutez-le :
gem sources -a http://gems.github.com
Puis installez le gem.
gem install dmathieu-dont_repeat_yourself
Vous constaterez que je vous fait installer non pas la version de Jean-Michel, mais la mienne. Les explications viennent plus bas.

Une fois que cela est fait, vous pouvez utiliser le plugin de trois manières possibles.

Dans vos tests

Avec Test::Unit

Créez le test suivant :
test "we don't repeat ourself" do
  assert_dry(rails_application.with_netbeans_reporting)
end

Avec RSpec

Créez le test suivant :
describe "Dupplicate lines Report: Don't Repeat Yourself" do
  it { ruby_project(File.dirname(__FILE__) + '/../').
    with_threshold_of_duplicate_lines(4).
    with_netbeans_reporting.
    should follow_the_dry_principle }
end

En ligne de commande

Tapez la commande suivante
dry-report

Ces rapports DRY sont même encapsulables dans Netbeans ou Textmate. Mais je n’ai pas encore penché mon nez là-dedans. Donc je vous laisse regarder ;)

Vous constaterez par ailleurs que je vous invite à installer le fork que j’ai fait du gem et non pas la version originelle.
La raison à cela est que en Rails 2.3, Test::Unit deviens ActiveSupport::TestCase.
Cette modification n’a pas encore été appliquée au gem originel. Mais je suis persuadé que cela ne saurait tarder ;)

Lorsque j’étais en Picardie la semaine dernière, en discutant avec Joris, nous en venons à parler de nos plateformes de développement personnelles.
Du coup forcément je lui explique l’architecture contraignante que je m’impose (développement local -> commit svn -> test sur serveur de préproduction -> push en production).

Et la il me dit « je n’ai jamais compris l’utilité de SVN ». Honte sur lui que je dis. Et je m’engage à lui expliquer cela.
Comme après on est arrivés au bar, je n’ai pas eu le temps de le faire. Mais c’est tous bénéfices pour vous puisque je le fais donc maintenant :)

Commençons par un peu d’histoire. Il y a trois générations de grands systèmes de gestion de version.

Il en existe d’autres évidemment. Mais je les épargne. Ce billet n’est pas là pour faire une liste de tous les systèmes de gestion de versions.

Alors comment ça fonctionne ? C’est au final assez simple.
Lorsque vous développez votre application seul et toujours sur la même machine, il est assez aisé de s’y retrouver. Vous avez toujours les dernières modifications de disponibles en local.

Le jour ou vous commencez à développer à deux ou à passer d’une machine à l’autre par contre, c’est plus embêtant.
Si vous êtes toujours seul, il vous suffirait d’une clé usb pour avoir toujours tous vos documents. Quand vous êtes à deux en revanche, cela n’est pas faisable.

Et c’est la qu’intervient le contrôle de versions.
Supposons trois fichiers : A, B, C

Vous modifiez le contenu du fichier A. Pendant ce temps un second développeur modifie le contenu du fichier B.
Ici on a que trois documents. Du coup il n’est pas difficile de s’y retrouver et de merger les modifications. Mais sur des gros projets ?

En faisant un commit sur votre contrôleur de versions, vous ne mettrez donc que le fichier A à jour. Le second développeur ne perdra pas ses modifications.
Et lorsqu’il mettra à jour sa version locale avec la version distante, il récupèrera le contenu du fichier A tel que vous l’avez modifié.

Poussons maintenant le vice plus loin :)
Le document A est particulièrement long et vous modifiez le début de celui-ci, les lignes 50 et 75 par exemple.
Le second développeur modifie les lignes 60 et 160.

Eh bien vos modifications pourront toujours être prises en compte par le contrôleur de versions, qui verra les lignes que vous avez ajouté dans le document et celles que vous avez modifié et sera capable de ne modifier que cela :)

On ira pas plus loin que cela. Il ne faut pas bousser le bouchon trop loin et il n’est pas capable de merger des modifications sur la même ligne.
En revanche, vous pouvez lui demander un café et voir ce qu’il répondra.

Ensuite, ous constaterez rapidement, en faisant quelques commits sur le contrôleur de version que vous pouvez placer un commentaire sur chacune d’elle.
Ainsi vous avez un historique de toutes les modifications apportées à chacun des fichiers de votre projet (et par qui).

C’est notamment fortement pratique dans un projet libre.  Vous pouvez par exemple suivre toutes les modifications apportées à votre projet préféré.
Voici un exemple. Il s’agit du dernier commit fait sur Ruby on Rails, durant la nuit (heure française).

Pour finir, quel contrôleur de version choisir ?
J’en utilise pour ma part, deux. SVN, sur ma machine de développement pour tous mes projets privés.
Et GIT sur github.com pour mes projets publics.

Entre les deux, je préfère git. Principalement car celui-ci implémente le contrôle de version complet en local. Vous pouvez donc faire votre commit en local puis le « pusher » et il sera en ligne. Ainsi, lors d’un voyage en train, je développe en découpant en commits lisibles et fait un push en arrivant. C’est comme si j’avais eu un accès internet durant mon voyage :)
Alors que les commits SVN font directement la mise à jour sur le serveur. C’est un peu moins propre.

Mais je fais face à quelques problèmes pour installer un serveur git sur ma machine. Pour l’instant, je dois donc encore me contenter d’un svn. Mais cela ne saurait tarder à changer.

Pour ceux qui ne connaitraient pas encore Git, c’est un logiciel de contrôle de version.
Celui-ci prends beaucoup d’ampleur depuis un an et pourrait être le remplaçant de SVN dans un futur proche.

Peut-être avez-vous également entendu parler de GitHub, qui héberge des projets en permettant leur gestion avec Git.
Quelques logiciels permettent d’installer le logiciel sur sa plateforme, que cela soit pour Windows, Mac OS X ou Linux.

Je n’ai pas testé sous Linux. Cependant sous Windows, j’ai opté pour msysgit. Et sous Mac, Git-Osx-Installer.
Je vous laisse les installer. Attention, sous Mac OS, il y a deux logiciels à installer. Tout d’abord Git, qui apportera les commandes console néessaires. Puis OpenGitGUI qui apportera une interface graphique.

Open Git GUI

Une fois que c’est installé, lancez Open Git GUI. Puis créez un nouveau repository. Placez-le dans le répertoire de votre choix.
Une fois que cela est fait, nous pouvons configurer GitHUB afin de pouvoir pousser nos commits là-bas et y héberger notre projet.

Puis rendez-vous sur GitHub et cliquez sur le lien « account » en haut à droite.
La, la page de modification de votre compte s’affichera. Si vous descendez dans la page, vous verrez un paragraphe intitulé « SSH Public Keys ».

Il vous faut créer une clé pour chacune des machines depuis laquelle vous manipulerez le projet. Chaque clé est unique à la machine, pas au projet.

Pour connaitre la clé de la machine, retournez dans OpenGitGUI et cliquez sur le menu « aide » puis sur « montrer la clé SSH ».
Si vous n’avez pas encore généré de clé, le bouton « Générer une clé » sera alors accessible. Sinon, cliquez copier dans le presse papier et placez cette clé sur GitHub.
Attention ! Connaitre cette clé permets à n’importe qui de commiter sur tous vos projets hébergés sur GitHub. Ne la partagez pas.

Une fois que ceci est fait, il faut ajouter un dépot distant sur GitHub. Cliquez sur « Dépôt distant » puis « ajouter ».
Donnez-y le nom de votre choix. L’emplacement est indiqué par GitHub, de la forme git@github.com:vous/votre-projet.git

Comme le projet est nouveau, il faut y ajouter les nouveaux fichiers. Faites donc « Commit » puis « Indéxer ».
Placez un commentaire de commit en bas à droite, puis commitez (une ou plusieurs fois afin de séparer vos diverses modifications) puis poussez vers GitHub :)
Rendez-vous sur la page de votre projet et vous pourrez constater que celui-ci est correctement hébergé là-bas.

 
Fork me on GitHub