Développeur web touche à tout (ou presque)
In: Développement
3 juil 2009Je 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 !!)
In: Films
1 juil 2009Comme en mai, voici ma liste de films pour juin.
In: Ruby
29 juin 2009Il 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
In: Général
27 juin 2009
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 !
In: Django
25 juin 2009Quelque 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
In: Python
23 juin 2009Derriè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).
In: Général
22 juin 2009Stop ! 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
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.
In: Général
18 juin 2009Le 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 !



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
In: Rails
17 juin 2009Je 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 ![]()
Et si vous utilisez Test::Unit, je vous invite à tester RSpec. Vous voudrez plus faire que de ça après
In: Rails
16 juin 2009Vous 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.