Damien Mathieu

Blog d’un développeur web

Rails : tester l’envoi de fichier

novembre27

Rails ça rox ! Mais comme pour tout, il faut correctement l’utiliser.
Et pour cela, il faut faire des test. Pas manuels, mais automatiques. Je vous laisse découvrir cela.

Cependant il y a certaines choses qui ne sont pas forcément pratiques à tester, tel que l’envoi d’un fichier.
Vous avez besoin d’un objet spécial toussa. Pas bien difficile dans l’idée. Mais tellement chiant pour un bon fainéant comme moi ;-)

Si vous avez lu l’article donné plus haut, vous avez vu la page “Testing Files Upload” qui, fonctionne bien.
Ou presque, malheureusement.
En effet l’attribut content_type est, dans “la vraie vie”, modifiable. Et ici, il est disponible uniquement en lecture. C’est bête, ça fait planter votre test alors que l’application fonctionne bien.

Mais il y a une solution heureusement ! La voici :)
En cherchant un peu, j’ai découvert que Rails propose une méthode permettant de tester l’envoi de fichier, méthode qui est disponible en interne.

ActionController::TestUploadedFile.new(Test::Unit::TestCase.fixture_path + 'myfile.jpeg', content_type)

Ok, cool. Si vous testez cela déjà, vous constaterez que vous avez correctement votre objet pour tester le fichier envoyé. Super !
Seulement vous ne pouvez toujours pas modifier la valeur de content_type. Alors que l’objet retourné par un vrai fichier envoyé le permet.

Allons donc un petit peu hacker Rails.
Ouvrez le fichier RUBY_PATH/gems/1.8/actionpack-2.0.2/action_controller/test_process.rb

Puis cherchez la déclaration de la class TestUploadedFile
La, vous verrez la ligne suivante :
attr_reader :content_type

Nous avons donc l’attribut content_type en lecture. Passons le en lecture-écriture :
attr_accessor :content_type

Et hop ! Vous pouvez maintenant tester votre envoi de fichier tout en modifiant le content_type :)
Et moi dès que j’aurai trouvé un client GIT potable sous Windows, je pourrais proposer le hack à l’équipe de développement de Rails.

[Edit : Après avoir récupéré la dernière nightly build de Rails, le bug du attr_accessor a été corrigé. Si vous avez la dernière version de Rails, il n'est donc pas utile de faire cela]

posted under Rails | 3 Comments »

Zend Framework en MVC : charger les modèles proprement

novembre25

Ceux qui me connaissent le savent : je fait beaucoup de critiques sur le Zend Framework n’aimant pas vraiment les mauvaises habitudes de développement qu’il permet de prendre et les répétitions inutiles de code qu’il incite.
Je suis un fort partisan du DNRY (Do Not Repeat Yourself) et je ne m’en cache pas.

Cependant il est plus facile de vendre du Zend Framework qu’un autre framework que je ne nommerais pas mais qui a une équipe de développement non réactive et qui semble se reposer sur ses lauriers.
Alors je m’adapte et je tente de faire des trucs propres avec Zend Framework.
Et c’est faisable !!!

L’un des gros problèmes que je donnais au framework est le fait qu’il n’y a aucun chargeur automatique des modèles lorsque l’on utilise le framework en mode MVC. Il nous fallait donc faire quelque chose comme :

require_once APPLICATION_PATH . '/models/Users.php';
$this->Users = new Users();

Et ce dans chacun de nos contrôleurs qui utilise ce modèle. Pas cool.

Avoir quelque chose comme cela lors de la déclaration du contrôleur serait plus joli :
var $uses = array('Users');

Alors implémentons-le !
Tout d’abord, il nous faut déclarer ce que j’appelle un AppControlleur.
Il s’agit d’un contrôleur qui n’est jamais appellé seul. Il étends Zend_Controller_Action.

Chacun de nos contrôleurs étendra cet AppController. Ainsi, toute méthode présente dans celui-ci le sera dans le notre.

Donc, créons notre fichier dans le répertoire “application” de celle-ci. Nommons le AppController.php

Voici son contenu :
class AppController extends Zend_Controller_Action {
}

Puis il faut que nous inclusions notre AppController dans l’application. Dans bootstrap.php, après avoir défini la constante APPLICATION_PATH, placez :
include(APPLICATION_PATH . '/AppController.php');

Puis déclarez vos contrôleurs habituels de la manière suivante :
class MonController extends AppController

Voila, rechargez votre page. Si vous n’avez pas d’erreur, votre AppController est correctement chargé.
Super me direz-vous ! Mais ou ça m’amène ?

Eh bien maintenant, vous pouvez définir une méthode qui sera exécutée automatiquement à chaque chargement de page et qui chargera tous les modèles dont vous avez besoin.

Soyons fous, mettons à jour notre AppController :
class AppController extends Zend_Controller_Action {
function __construct($param, $param2) {
parent::__construct($param, $param2);
if (isset($this->uses))
foreach($this->uses as $model) {
if (file_exists(APPLICATION_PATH . '/models/'.$model.'.php'))
require_once APPLICATION_PATH . '/models/'.$model.'.php';
else
throw new Exception('Can\'t load model '.$model.' Please create the file \''.APPLICATION_PATH . '/models/'.$model.'.php\'');
if (class_exists($model))
$this->{$model} = new $model();
else
throw new Exception(APPLICATION_PATH . '/models/'.$model.'.php was supposed to declare class \''.$model.'\'');
}
}
}

Et voila ! Que faisons-nous ? Dans la méthode __construct, nous regardons si la variable de classe $uses est définie. Si c’est le cas, nous parcourons le tableau.
Pour chacun des éléments, nous vérifions si le modèle existe et nous le chargeons.

Puis nous vérifions si la class du bon nom existe et nous l’initialisons.

Et vous pouvez maintenant instancier tous les modèles de votre choix en une seule ligne de code dans chacun de vos contrôleurs.

posted under PHP | 12 Comments »

Ruby/Rails : number of week days between two dates

novembre24

It’s very easy, in Ruby, to count the number of days between two dates.

date1 = 1.month.ago
date2 = Date.today
puts date2-date1

However, you might need to calculate, not all the days between dates. But all the week days. For example if you’re working on an extranet and you want to count all the working days :)

Vamos ! Let’s put in your code (wherever you want. But put it somewhere logical please) :
class Date
def weekdays_until(date)
return 0 if date <= self
(self..date).select{|day| day.is_weekday?}.size
end
def is_weekday?
self.wday != 0 && self.wday != 6
end
end

And to use is :
1.month.ago.weekdays_until(Date.today)

Cool no ? :)

What are we doint ?
We overload the object Date by adding to it two new methods :
- is_weekday? which gives us true if the day is from monday to friday.
- weekdays_until which gives us the number of days from monday to friday only.

If course it doesn’t count the holidays ;)

Note : the tricks used here, like 1.month.ago are only available if you’re in a Rails environment. Otherwise, you have to calculate this by hand.

Ruby/Rails : Nombre de jours de semaine entre deux dates

novembre24

En ruby, il est très facile de compter le nombre de jours entre deux dates.

date1 = 1.month.ago
date2 = Date.today
puts date2-date1

Cependant il peut arriver que vous ayez besoin non pas de calculer le nombre de jours entre deux dates … Mais le nombre de jours de semaine (du lundi au vendredi) entre deux dates.
Dans le cas d’un extranet pour calculer le nombre de jours travaillés, cela peut s’avérer très utile :)

Vamos ! Placez, dans votre code (dans l’idée, n’importe ou. Mais mettez le à un endroit ou vous le retrouverez. Sinon, vous allez rapidement perdre le contrôle de votre application) :
class Date
def weekdays_until(date)
return 0 if date <= self
(self..date).select{|day| day.is_weekday?}.size
end
def is_weekday?
self.wday != 0 && self.wday != 6
end
end

Et pour l’utiliser :
1.month.ago.weekdays_until(Date.today)

Cool non ? :)

Que faisons-nous ?
Nous surchargeons l’objet Date en y ajoutant deux nouvelles méthodes :
- is_weekday? qui nous retourne true si on est du lundi au vendredi.
- weekdays_until qui nous calcule le nombre de jours du lundi au vendredi seulement.

Evidemment, cela ne prends pas en compte les vacances scolaires ;)

Note : les “tricks” 1.month.ago ne sont disponibles que si vous êtes dans un environnement Rails. Dans le cas contraire, il vous faudra calculer la date passée manuellement

posted under Ruby | 2 Comments »

Spoil

novembre23

Désolé pour la mauvaise qualité de la photo, prise avec mon nokia e71 à la fnac.

Arrivée prévue fin 2008 - début 2009 …

posted under Général | No Comments »

Let’s kill the trollers

novembre20

A french guy, named Eric Dupin closed his blog, called presse-citron because he’s tired of all the trolls in comments there. It’s only temporary as he’s planning to come back. But I want to react on that action.
Not because I don’t support it, all the contrary.

Even though I don’t really like the guy, who fakes to be an expert to make money with his blog, I completely agree with this action he’s doing. I am also tired of all those trollers.

A lot of web users thinks they can do anything on the internet because on the first look, anyone seems to be anonymous. But this anonymity is as virtual as all the web is. And Eric isn’t the only one to manage newbies who are really good at criticism. But not constructive critisicm.

As an example, until last year, I was moderator on a french SEO forum, called WebRankinfo. There was there an ODP forum for which only utility was to provide informations to users and allow communication between editors and users.
Well this forum have been closed one year and a half ago because of those trollers who made it’s management unbearable.
I was moderator there at that moment. And the trolls were depressing like you can’t imagine from my editor point of view.

So Mr. Dupin, my only message is : you’re not the only one to have to manage that kind of message in permanence. Be brave. You’ll see with time, you’ll learn to ignore them and forget them 3 seconds after reading it.

Note : because of battery problems, there’s no photo at the end of my articles for now.

posted under Others | No Comments »

Eric il a pas tort

novembre20

J’ai tendance à ne pas apprécier le contenu que Eric Dupin place sur son blog, presse-citron.
Pseudo-expert qui fait des billets sur des sujets qu’il ne maitrise pas dans le but de rentabiliser un blog lu par des gens qui le fanatisent. Très peu pour moi.

Cependant je suis plutôt d’accord avec son dernier billet, fermé pour cause d’inventaire.
Passons tous le problème personnel.

Mais le web est constitué de boulets trollers qui s’imaginent être à l’abri de tout derrière leur écran. Alors que comme tout sur le web, l’anonymat y est virtuel. Et Eric n’est pas le seul à subir ces boulets qui sont très forts dans la critique négative mais ne connaissent pas la critique constructive.

Comme exemple, je prendrais simplement le cas du forum dmoz sur WebRankInfo, dont la seule utilité était de permettre aux webmasters de s’informer sur l’ODP et de converser de manière directe avec les éditeurs.
Ce forum a été fermé il y a de cela un an et demi suite justement à ces trollers qui rendaient sa gestion intenable.
J’y était modérateur à cette époque. Et les trolls à cet endroit étaient plus que déprimants de mon point de vue d’éditeur.

Alors monsieur Dupin, mon seul message, c’est : tu n’es pas tout seul à supporter ce genre de messages quasi permanence. Courage. Tu verra avec le temps, tu apprends à simplement les ignorer et les oublier 3 secondes après les avoir lus.

Note : j’ai des problèmes de batterie en ce moment. Impossible d’utiliser mon appareil jusqu’à ce que deux colis qui viennent de Hong Kong soient arrivés à Lyon. Donc en attendant, pas de photo de fin d’article. Désolé.

posted under Général | 8 Comments »

Paris Web 2008

novembre16

J’étais, hier, aux ateliers de Paris Web 2008. Petit compte rendu des divers ateliers auxquels j’ai participé :)

Javascript De(ux) Zéro
mat nous proposait un rappel pas superflus des bases de Javascript, de ses fonctionnalités avancées, des diverses incompatibilités inter navigateurs et des évolutions du langage.

Performance Web côté client
Eric Despet et Nicole Sulivan ont pris divers sites en exemple afin de les analyser, de signaler leurs problèmes de performances et de proposer des solutions pour les corriger.

Comment rendre mes vidéos accessibles ?
Sébastien Delorme nous présentait les diverses manières de rendres des vidéos (diffusées sur le web ou pas) accessibles. Création et synchronisation de sous-titres, création et synchronisation de commentaires audio.
Application de ces sous-titres et commentaires audio dans RealPlayer et dans divers lecteurs flash.

Optimiser ses CSS
Pascale Lambert-Charreteur, assistée de Stéphane Deschamps et d’un troisième que je ne connais pas, nous présentaient diverses techniques afin de préserver sa feuille de style CSS propre, lisible et légère.

A tous ces ateliers plus intéressants les uns que les autres, il faut ajouter :
Un repas le midi avec Pascal Martin, gérant de la société Linterweb qui développe notamment Wikiwix (et plein d’autres choses en rapport avec la recherche et/ou Wikipédia).
Un repas sympa, passé à discuter de ses divers projets et de ses évolutions futures.

Puis pour finir la soirée en beauté, j’ai retrouvé tuisp, inistea, rome et sahinler pour un repas entre éditeurs dmoz.

Malheureusement, pas de photos de ce week-end à Paris. En effet, bien que j’ai mis la batterie de mon appareil à recharger jeudi toute la journée et que je ne l’ait pas utilisée entre temps, je me suis rendu compte samedi matin que je n’avais plus d’énergie.
La raison exacte de ce déchargement aussi rapide est encore un mystère. Mais que je résoudrai bientôt. Désolé, la photo de fin d’article n’est donc pas récente.

posted under Général | 2 Comments »

Les banques à la masse niveau sécurité

novembre4

Aujourd’hui, je renouvelle l’un de mes noms de domaine. Par carte de crédit bien évidemment.
Et la, pour la première fois, ma banque, le Crédit Agricole, me demande de définir un mot de passe que je devrai apparemment retaper à chaque utilisation de ma carte.

Sur le coup, je me dis “ouah, super idée. Enfin la faille de sécurité énorme au niveau des paiements par carte bancaire sur Internet ne demandant pas de code va être corrigée”.

Je tape donc un code. Et la, surprise !
Il y a des conditions requises au niveau du mot de passe.

Mais, contrairement à ce que l’on est habitué à avoir, c’est à dire des conditions favorisant la sécurité, on a ici le contraire.

  • Le code ne peut contenir que des caractères alphanumériques.
  • Il a une longueur de 6 caractères. Pas plus, pas moins.
  • Il doit contenir au moins un chiffre et une lettre.

Rien à redire sur le dernier. C’est les deux autres qui sont nuls.
Pourquoi limiter à 6 caractères ?? Encore dire “6 caractères minimum”, je comprendrais. Mais si j’ai envie de mettre un mot de passe à 8 caractères, c’est plus sécurisé et ça coute pas plus cher.

Et pourquoi limiter aux caractères alphanumériques ? Si j’ai envie de mettre un “;” ou un “^” dans mon mot de passe, en quoi ça gène le stockage ou que ce soit ??
Les banques ont 10 ans de retard d’un point de vue sécurité. Et pourtant on ne peut pas dire que les données qu’ils font transiter ne sont pas sensibles.

posted under Général | 7 Comments »

Zend Framework et Mysqli

novembre3

Je publie ce billet un peu rapidement comme une note car j’ai eu du mal à trouver l’information lorsque j’en ai eu besoin.

La documentation de Zend Framework n’indique que les informations de connexion pour SQLite dans app.ini.
Mais tout le monde n’utilise pas SQLite (et pour donner un avis totalement personnel, je dirais heureusement).

Voici donc les informations requises pour la configuration de MySQL dans votre application utilisant Zend Framework.

[general]
database.adapter = “MYSQLI”
database.params.host = “localhost”
database.params.username = “root”
database.params.password = “”
database.params.dbname = “myDatabase”

Et puis rien que pour le fun, Oracle :
[general]
database.adapter = “Oracle”
database.params.host = “localhost”
database.params.username = “root”
database.params.password = “”
database.params.dbname = “myDatabase”

SQL Server
[general]
database.adapter = “Pdo_Mssql”
database.params.host = “localhost”
database.params.username = “root”
database.params.password = “”
database.params.dbname = “myDatabase”

Et PostgreSQL
[general]
database.adapter = “Pdo_Pgsql”
database.params.host = “localhost”
database.params.username = “root”
database.params.password = “”
database.params.dbname = “myDatabase”

posted under PHP | 4 Comments »
« Older Entries

Rss Feeds

En Français
In English