Je ne m’en cache pas, je suis un pro git à fond.
Cependant et malheureusement, git n’est pas (encore) très répandu et beaucoup de projets sont encore hébergés sur des repositories SVN.
C’est le cas chez O2Sources (mais on parle d’y remédier, notamment lorsque Townce gèrera cela).

Vu que je viens de migrer ma machine de Windows vers Ubuntu, j’ai décidé d’en profiter pour faire un test.
Utiliser git-svn pour commiter en local en git et pousser par la suite sur le repository svn :)

Déjà, l’installation. Sous Debian-Like,
sudo aptitude install git-svn
Normalement, cela vous crée une commande « git-svn» . Moi, ça l’a pas fait. Du coup un petit coup de sudo find / -name git-svn; vous trouvez l’emplacement de l’exécutable (théoriquement dans /usr/bin) et y créer une commande globale.
ln -s /chemin/vers/git-svn /usr/bin/git-svn

Ensuite, commençons par récupérer notre repository
git-svn clone -s http://domaine.net/chemin/vers/le/repository
Si vous avez une arborescence avec des tags (dossiers tags/, trunk/ et branchs/), placez l’option -s.
Ainsi, git-svn les convertira en tags et branches GIT.
Sinon, c’est inutile :)

Deuxième étape : si vous avez des options git:ignore, elles ne sont pas prises en compte. Faites les donc :
git-svn show-ignore > .gitignore

Maintenant, faites vous une session de développement. Committez comme d’habitude sur votre repository git et oubliez svn (youpi !!).
Une fois que celle-ci est terminée, il vous faut committer (bah ouais hein).

Pour cela, commencons par faire un update. On sait jamais que vous seriez pas le seul à travailler et que l’un de vos collègues n’ait committé entre temps ;)
git-svn rebase
Et committons
git-svn dcommit

Vous verrez que votre repository svn a été mis à jour.
Cool non ? :)
Et vous, vous préférez GIT ou SVN ? (ouais, postez des commentaires !!)

Comme en mai, voici ma liste de films pour juin.

  • Looking for Eric
    Note : 7 / 10
    N’étant absolument pas intéressé par le foot, je ne voulais au début pas aller voir ce film. Et puis ayant entendu des bonnes critiques, j’ai changé d’avis.
    Et j’ai grandement bien fait ! Une superbe comédie qui ne vole pas très haut du point de vue de jeu des acteurs. Mais dont la morale est magnifique et qui offre de nombreux éclats de rire.
  • Ne te retourne pas
    Note : 3 / 10
    Peut-être que en regardant ce film tout en ayant fumé avant, on comprends un peu mieux.
    Pour ma part, soit je n’ai pas compris grand chose; soit des énormes inepsies se sont glissées un peu partout. A cela il faut ajouter le jeu horrible de Thierry Neuvic. Un film plus que moyen au final.
  • Terminator : Renaissance
    Note : 4.5 / 10
    Ce film peut-il vraiment être classé dans la catégorie action ? On dirait vraiment du comique.
    Entre John qui se fait enlever sa chaussure au début par un Terminator et qui la retouve par magie et le Terminamoto qui a un port firewire, c’est vraiment rigolo.
    Heureusement pour ceux qui aiment l’action, on nous en met plein le nez. Et c’est ce qui rattrape la note (même si je ne pouvais pas sérieusement mettre la moyenne).
  • Les beaux gosses
    Note : 7 / 10
    Je ne m’attendais pas à rigoler autant. Les autres films du même genre (Lol; Nos 18 ans; …) sont généralement assez intellectuels. Ici, on ne se prends pas au sérieux et on rigole à vive voix pendant 1h30.
  • Je vais te manquer
    Note : 6 / 10
    En grand fan de Love Actually, j’espérais beaucoup de ce film. Malheureusement, bien que très touchant, très bien joué et réalisé, la recette est toujours la même et il n’y a pas de réelle surprise.
    Alors on passe un bon moment. Mais au final, aucune nouveauté. C’est une comédie romantique de destins croisés comme les autres.
  • Blood : the Last Vampire
    Note : 4 / 10
    Un scénario plutôt creux et ayant pour seul but (comme c’était, de toute façon, prévisible) de montrer du sang.
    Sang qui est, par contre, très mal représenté. Je ne savais pas que ça faisait des bulles quand on coupe des bras. A conseiller aux fans d’action et de Kill Bill like. Mais pas aux autres.
  • Tellement proches
    Note : 8 / 10
    Je tiens à saluer quelque chose d’exceptionnel de par ce film : la bande annonce ne spoil rien du tout de l’histoire !! Et ça, c’est particulièrement rare et fortement appréciable :)
    Par ailleurs le film est plein de pics, toujours criants de vérité et à hurler de rire. On y reconnait plus ou moins sa famille et on apprécie tout autant.
  • Lascars
    Note : 3 / 10
    Le comique de répétition c’est sympa. Mais faut que la blague soit drôle la première fois. Sinon c’est carrément lourd.
  • Jeux de pouvoir
    Note : 5 / 10
    On vois pas souvent des films ou le suspens du dénouement reste jusqu’à bout. Et même si on s’y perds quelques fois dans des déductions plutôt compliquées, l’histoire est particulièrement bien ficelée et mérite nos 2h d’attention.
  • Very Bad Trip
    Note : 5 / 10
    On regrette un petit peu le « happy end» . Mais on rigole de temps en temps et dans l’ensemble, on s’amuse.
  • Transformers II
    Note : 5 / 10
    On passera le manque de scenario. De toute façon, ce n’est pas le but de ce genre de film. En revanche, sur ce qu’il essaye de faire, nous en mettre plein la vue, il le réussit très bien et c’est tout ce qu’on lui demande.
  • Notorious Big
    Note : 6 / 10
    D’abord perplexe sur ce film, j’ai été fort agréablement surpris. Et bien que l’on ne s’identifie pas forcément aux personnages, on s’attache et on pleure.

Il est particulièrement simple, en Ruby, de parser un flux RSS.
Tout d’abord, dans le contrôleur, nous chargeons le contenu et le parsons :
require 'rss'
require 'open-uri'
@content = RSS::Parser.parse(open('http://feeds2.feedburner.com/DmathieuFr'), false)

La variable @content contiendra alors votre flux RSS parsé et chacun de ses éléments accessible.

Par la suite dans votre vue, vous pouvez récupérer les éléments de votre flux :
<ul>
  <% @content.items.each do |i| %>
    <li><%= link_to i.title, i.link %><br /><%= i.description %></li>
  <% end %>
</ul>

Nous bouclons sur chaque élément et affichons un lien pointant vers la balise link et ayant le titre; suivi du contenu.
Cela ne fonctionne évidemment que pour les flus RSS. Pour le XML en général, il faut utiliser REXML.

Pour finir (et parce que c’est dans le titre), il y a une petite exception pour le flux RSS de Flickr.
En effet, avec celui-ci, le parseur ne trouvera pas l’élément dateTaken mais date.Taken.
Il faut donc remplacer l’un par l’autre.

Voici donc le code de mon contrôleur :
@content = RSS::Parser.parse(open('http://api.flickr.com/services/feeds/photos_public.gne?id=23186094@N07&lang=fr-fr&format=rss_200').read.gsub!('date.Taken', 'dateTaken'), false)

Et dans ma vue, pour afficher les dernières photos postées sur mon pool :
<ul>
  <% @content.items.each do |i| %>
    <li><%= i.description %></li>
  <% end %>
</ul>

Et vous pouvez même voir la chose en action ! Sur mon portfolio :)

blague de merde

Venez les partager ! :)
Je l’ai un peu annoncé toute la semaine sur twitter avec les spoils suivant :

Mardi :

SPOIL : samedi dans l’après midi je lance un nouveau site !

Mercredi :

SPOIL : le contenu du site que je lance samedi est ce que @fvsch, @jeansboub & moi lançons à longueur de journée.

Jeudi :

SPOIL : c’est vous (et moi et tt le monde. Youpi !) qui ferez le contenu du site que j’ouvre samedi

Vendredi :

SPOIL : le site que je lance demain tournera avec Django. Mais ne parlera pas d’informatique, même si cela pourra être évoqué.

SPOIL le site que je lance demain vous fera bien marrer (enfin j’espere)

De nombreuses suppositions ont été faites, certaines plus proches de la réalité que d’autres.

Et je suis fier de vous le dévoiler aujourd’huiau maintenant :)
Je vous présente donc Blague de merde.
Vous pouvez, après vous être inscrit, poster toutes les blagues que vous désirez. Puis les visiteurs peuvent voter pour ou contre cette blague.
Les blagues ayant le meilleur score du moment seront affichées le plus haut.
C’est donc un digg-like de toutes les blagues de merde et à la con que vous pourrez trouver.

Alors à vos clavier pour raconter vos blagues ! :)

Django : les slugs

In: Django

25 juin 2009

Quelque soit le langage, un élément est toujours délicat à traiter : créer des url cool, avec des vrais mots.
Mais en ne plaçant pas de caractères qui vont rendre l’url toute pas jolie avec des %20 et autres.

Pour cela, il faut supprimer tous les accents (et les remplacer par leur lettre sans accent); supprimer les espaces (et les remplacer par des -) et supprimer les signes de ponctuation (et ne pas les remplacer).

Avec Django, pas besoin de s’embêter avec ça :)
Il y a les slugs.
Par principe, un slug contiendra toujours une valeur qu’il est possible de mettre en url et sera toujours unique.
A vous par la suite de l’utiliser pour créer l’url de vos objets.

Mais il faut encore le définir correctement :)
Pour cela, dans votre administration, nous allons placer un prepopulated_field.
Placez dans vos fieldsets le titre de l’uplet et son slug.

Puis placez le code suivant en dessous de la définition des fieldsets :
prepopulated_fields = {'slug': ('title',)}
Ou slug est le nom du champ « slug»  (je vous conseille de l’appeller slug).
Et ou title est le nom de votre champ de titre.

Chargez votre administration, remplissez votre titre et admirez votre champ de slug se remplir tout seul :)
Vous constaterez également qu’il ne se remplit que lors de la première édition, pour éviter un changement d’url inopportun lorsque vous changez le titre de la page.
Rien ne vous empêche par ailleurs de placer le slug de votre choix.

Vous pouvez par ailleurs personnaliser la chose dans votre application.
Par exemple dans un template, pour afficher la valeur d’un string slugifié :
{{ "mon Test"|slugify }}
Affichera : mon-test

Et dans vos fichiers .py directement également
from django.template import defaultfilters
slug = defaultfilters.slugify("Mon Test")

la variable slug contiendra alors mon-test.

Et vous pouvez faire de belles URLs. N’oubliez pas d’utiliser les vues génériques pour trouver le contenu qui correspond à un slug et le charger :)

Derrière ce mot compliqué « circulaire»  se cache l’un des effets pervers de Python.
En effet, pour obtenir accès à des méthodes situées dans des fichiers différents, Python requiert que l’on importe celles-ci.

from mon_fichier import ma_methode
Dans l’idée, c’est cool. Ca permet de ne charger que la méthode désirée en mémoire et évite la surcharge.

Dans la pratique, supposons le cas suivant :
- Un fichier comments.py, qui contient la méthode getPost.
Cette méthode permet d’obtenir le billet dans lequel a été fait le commentaire.
- Un fichier posts.py, qui contient la méthode getComments.
Cette méthode permet d’obtenir tous les commentaires d’un billet.

Dans comments.py, vous faites :
from posts import *
Avec un * parce que vous désirez pouvoir obtenir non seulement le getComments, mais également toutes les méthodes de posts, qui peuvent être aussi diverses que votre imagination le permet.

Dans posts.py, vous faites :
from comments import *
Le *, pour la même raison que précédemment.
La, c’est balot. Mais le second import ne fonctionnera pas.
Avec une erreur du genre :

NameError: name ‘getPost’ is not defined

Python n’arrive pas à charger la classe posts car elle a déjà été chargée auparavant.

Heureusement, nous avons une solution ! :)
Ne faites pas de from class import *. Mais plutôt :
import posts
import comments
La différence est au premier abord anodine. Nous n’aurons plus accès directement à notre méthode getPost, mais à comments.getPost.
Du coup nous allons, en spécifiant l’espace de noms, pouvoir inclure nos classes en les croisant, l’une dans l’autre.

Je ne suis pas sur que cela soit très clair et je ne vois pas trop comment expliquer cela différemment. Donc un petit résumé :
Si vous cherchez à importer une méthode de la classe qui a importé la méthode dans laquelle vous êtes (la, déjà, si vous êtes perdus, on est mal barrés), ne faites pas de from class import method
Mais plutôt un import class.
Puis appellez votre méthode avec un class.method.

Merci à Philippe et à Guillaume Ayoub (pour qui je n’ai pas de lien. Si il passe par ici, qu’il n’hésite pas à faire signe).

Stop ! Arrêtez de vous faire des films mesdemoiselles. Je sais que vous êtes toutes folles de moi ;)
Plus exactement, le titre de ce billet est le contenu d’un tweet que j’ai lancé ce jour en début d’après midi.

En bon blogueur influent que je suis (ahem … ou pas), cela m’a apporté … 4 nouveaux followers.
Merci donc à lavraiemadamel, Kyotoweb, CyrilGarin et Guzol.
Vous pouvez me défollow maintenant. C’est fini.
On notera tout de même que parmi ces 4 nouveaux followers, il y a deux mecs, une femme mariée et une autre qui pourrait avoir mon âge (j’avoue ne pas avoir passé des heures à chercher).
A ces 4 courageux, il faut ajouter une bonne vingtaine de personnes. Je ne les citerai pas tous, qui ont retwitté la chose.

Du coup ça fonctionne moins bien que ce qu’avait fait Marion il y a quelques mois et qui s’est visiblement fini avec un coup de langue.
On dira que c’est parce que je suis un mec et que les tweeteuses sont timides. Vous pouvez donc m’envoyer un email mesdemoiselles. Cela restera entre nous :mrgreen:

Quoi qu’il en soit, c’est une tentative faite pour gagner tout plein de followers sur Twitter. Et c’est râté.
Probablement parce que j’ai repris une idée déjà utilisée en effet, mais n’empêche.

Le coca c’est bien. Mais au bout d’un temps, c’est pas super cool pour l’estomac.
Du coup il faut que je boive du thé (je ne bois pas de café).
Mais j’avais, jusqu’à ce matin, aucun mug sympa dans lequel boire mon thé.

C’est maintenant chose reglée. Et évidemment c’est un truc de geek dans le genre que je suis !


Etant gaucher, le vois le logo Rails lorsque je bois mon thé.


Si je tourne un peu le bol, on me rappelle à l’ordre en me disant que PHP, ça existe aussi.


Et en finissant la rotation, je découvre que y’a également Django, qui rox tout autant que les deux précédents.

C’est pas du bon mug de geek ça ? ;p
Et vous pouvez même faire le même si ça vous chante.
Voici le modèle.
Et pour la commande, je suis passé par MyPix. On en a commandé trois avec Floriane et on en a eu pour une dizaine d’euros chacun.
Le tout livré en 72 heures ouvrées :)

Je suis un peu genre obsédé par les statistiques de mes applications.
Du coup beaucoup d’entre elles ont des outils me permettant de générer des graphiques avec divers indicateurs d’évolution des données de celles-ci en fonction du temps.
Sur RefStats par exemple, ce graphique m’affiche l’évolution du nombre de positions; du nombre d’utilisateurs; de sites et le temps moyen d’exécution du robot pour chaque mot clé.

Par ailleurs vous connaissez probablement déjà la commande Rails rake stats qui fournit des données statistiques sur le code de votre application. Nombre de lignes de code; nombre de lignes de test; ratio, …
La classe calculant ceci est située dans les railties.
Malheureusement cette classe n’est pas vraiment abstraite. Elle affiche directement des données en console, c’est pas super cool pour les entrer en base de données.

Du coup j’ai repris cette classe pour la modifier et permettre de récupérer ces données de manière abstraite et ainsi pouvoir les utiliser dans mon application :)
Je vous présente donc Rails Code Statistics (oui j’ai toujours des super idées de noms de projets).

Le principe est archi simple.
Vous instanciez la classe :
stats = CodeSearch.new

Puis vous pouvez récupérer les données comme un hash :
p(stats.to_h)
Comme un élément json
p(stats.to_json

Uniquement les statistiques totales
p(stats.total)
Uniquement les statistiques détaillées
p(stats.statistics)

Et après en faire ce que vous voulez :)
Dans mon cas par exemple, j’ai une tache rake qui est exécutée automatiquement une fois par jour et qui me place le nombre de lignes de code et de tests.
Ainsi je n’ai plus qu’à traiter ces données pour faire un graphique d’évolution de mon application.

Note : la version ci-dessus ne fonctionnera que si vous avez vos tests faits avec RSpec.
Si vous utilisez Shoulda, je vous laisse vous débrouiller :mrgreen:
Et si vous utilisez Test::Unit, je vous invite à tester RSpec. Vous voudrez plus faire que de ça après :mrgreen:

Vous le savez probablement déjà, il est possible, avec Active Record, de faire vos conditions proprement de deux manières différentes :
Model.find(:all, :conditions => ['champ = ?', valeur])
Model.find(:all, :conditions => {:champ => valeur})

Le second est plus propre. Cependant à première vue, il n’est pas possible d’y faire des conditions autres que le égal (=).
Du coup dès que votre condition devient un chouilla complexe, il deviendrait nécessaire d’utiliser les crochets. C’est dommage.

Heureusement, il des conditions autres que le = sont gerées avec les hashes.
Petit exemple de requête
Model.find(:all, :conditions=>{
:title => "Title",          # title='Title'
:published_at => (Date.now-30 .. Date.now),  # published_at BETWEEN xxx AND xxx
:rating => [ 4, 5, 6 ],          # rating IN ( 4, 5, 6 )
:content => /(a|b|c)/          # REGEXP '(a|b|c)'
)

Cela permet déjà de faire quelques requêtes supplémentaires. Cependant dès que l’on va vouloir faire des choses comme des LIKE, des !=, des >= ou des <=, nous allons, de toute façon, devoir passer par des tableaux.

Photostream

    FlorentPhilou vs 5DMadagascarHélèneLucienPhilou vs langueMug DesignRails TeaPHP vs. Django

Rss Feeds

En Français :


In English :