The Caribbean Weblog

"This blog is continuing @ http://christophemaximin.com "

Aller au contenu | Aller au menu | Aller à la recherche

mardi 27 mars 2007

2007raisons.com

Je viens à l'instant d'ouvrir un nouveau site, http://www.2007raisons.com (RubyOnRails powered) dont voici la "définition" :

Qu'est-ce que 2007raisons.com ?
C'est un site permettant aux internautes de d'exprimer leur avis sur l'élection présidentielle française de 2007, du 22 avril puis du 6 mai.

Le concept
Plutôt que de proposer un sondage habituel sur les intentions de votes, ce qui n'a pas vraiment de sens visible pour les autres internautes, nous proposons un système tout à fait nouveau mais très efficace : nous invitons les internautes à dire pourquoi ils voteront pour un(e) candidat(e) en particulier, en une ligne et dans un maximum de 200 caractères.
Cette technique permet de savoir ce que pensent les électeurs de leur candidat(e), et de cerner ce qui, au-delà des autres raisons les pousse à effectuer ce choix.
De plus, nous proposons aussi à l'internaute de dire pourquoi il ne votera pas pour un(e) candidat(e), ce qui permet cette fois de cerner la caractéristique du candidat la moins séduisante selon l'internaute.

Quelques soient les raisons, aussi farfelues qu'elles pourront sembler, nous les conserverons avec soin, car pensons cette méthode vraiment efficace au point de tenir un pari, publiquement.

mercredi 14 mars 2007

Rails : Avoir des noms de jours/mois en français -- Override Dates

Ce qui suit permet de franciser les élements de Date et de les rendres disponibles dans les formats de sortie de Time.

Donc, avec table People et un champ created_at en datetime (que ActiveRecord renseignera automatiquement à la création de la ligne), l'on pourra faire Person.find(:first).created_at.to_s(:fr_long) ce qui donnera quelquechose comme mercredi 14 mars 2007 à 13h37. Ceci grace à ActiveRecord qui converti les champs SQL Date et DateTime en objets Time.

### config/environment.rb
# Include your application configuration below
[...]
require 'lib/date_overrides'
[...]
### lib/date_overrides.rb
Date::MONTHS.replace({'Janvier' => 1, 'Fevrier' => 2, 'Mars' => 3, 'Avril' => 4, 'Mai' => 5, 'Juin' => 6, 'Juillet' => 7, 'Aout' => 8, 'Septembre'=> 9, 'Octobre' =>10, 'Novembre' =>11, 'Decembre' => 12})
Date::DAYS.replace({'Dimanche' => 0, 'Lundi' => 1, 'Mardi' => 2, 'Mercredi' => 3, 'Jeudi'=> 4, 'Vendredi' => 5, 'Samedi' => 6})
Date::ABBR_MONTHS.replace({'jan' => 1, 'fev' => 2, 'mar' => 3, 'avr' => 4, 'mai' => 5, 'juin' => 6, 'juil' => 7, 'aou' => 8, 'sep' => 9, 'oct' =>10, 'nov' =>11, 'dec' => 12})
Date::ABBR_DAYS.replace({'dim' => 0, 'lun' => 1, 'mar' => 2, 'mer' => 3, 'jeu' => 4, 'ven' => 5, 'sam' => 6})
Date::MONTHNAMES.replace [nil] + %w(Janvier Fevrier Mars Avril Mai Juin Juillet Aout Septembre Octobre Novembre Decembre )
Date::DAYNAMES.replace %w(Dimanche Lundi Mardi Mercredi Jeudi Vendredi Samedi)
Date::ABBR_MONTHNAMES.replace [nil] + %w(jan fev mar avr mai juin juil aou sep oct nov dec)
Date::ABBR_DAYNAMES.replace %w(dim lun mar mer jeu ven sam)

class Time
  alias :strftime_nolocale :strftime

  def strftime(format)
    format = format.dup
    format.gsub!(/%a/, Date::ABBR_DAYNAMES[self.wday])
    format.gsub!(/%A/, Date::DAYNAMES[self.wday])
    format.gsub!(/%b/, Date::ABBR_MONTHNAMES[self.mon])
    format.gsub!(/%B/, Date::MONTHNAMES[self.mon])
    self.strftime_nolocale(format)
  end
end

# exemples de formats de date
Time::DATE_FORMATS[:fr_date] = '%d-%m-%y'
Time::DATE_FORMATS[:fr] = '%d-%m-%y %H:%M'
Time::DATE_FORMATS[:fr_long] = '%A %d %B %Y à %Hh%I'
Time::DATE_FORMATS[:frs] = '%d-%m-%y %H:%M:%s'

mardi 6 mars 2007

Où est GIMP ?

DMC ?

Regardez bien cette page : http://bayrou.fr/mentions/credits.html.
Et maintenant, devinez ce que va nous sortir cette commande :

wget http://bayrou.fr/img/gimp_logo.jpeg -O - | strings | grep CreatorTool

Réponse :

<xap:CreatorTool>Adobe Photoshop CS2 Windows</xap:CreatorTool>

Notez que toutes les autres images du site ont aussi été faites avec "Adobe" quelque chose...

dimanche 4 mars 2007

Rails : Ré-ordonner des lignes ActiveRecord

RubyLogo EDIT: Merci à Bounga de m'avoir montré "the right way"... ça m'apprendra à pas asser fouiller dans la doc... En fait, ruby permet de réordonner les résultats comme il faut, de cette façon :

Image.find(:all, :order => 'title').sort_by(&:id)

Voilà, c'est tout... donc en fait le helper qui correspondrait pourrait être :

def reorder_results(result, by = :id)
  result.sort_by(&by)
end

Fin. Le reste du billet sert juste d'explication au pourquoi de la méthode, le code même qui suit étant caduque.


Aujourd'hui, nous allons essayer de palier un "manque" de la classe Array, en rapport avec ActiveRecord (hein?)

Si, après être passé dans un filtre relativement compliqué, vous avez une liste de résultats activerecord, dans un array, à afficher, sachez que vous ne pourrez pas la -ordonner "comme ça".
En effet, en imaginant que nous utilisons une table "images", Image.find(:all).sort nous dit que les Image ne sont pas comparables (NoMethodError: undefined method `<=>' for #<Image:0x409c6bec>), ce qui est le cas des String, Integer et autres constantes "habituelles" de Ruby.

Donc sans hacker le coeur de ActiveRecord, on peut arriver au même résultat en utilisant ma méthode 'reorder_results' comme ceci :

a_classer = Image.find(:all)
reclasses = reorder_results(a_classer, :title)

Je tiens à re-préciser que oui, montré comme cela, ça n'a strictement *aucunt interêt* (totally useless). Oui, on aurait pu faire Image.find(:all, :order => 'title desc') directement, mais :
Imaginez qu'a la place de "a_classer", vous ayez un array de Image, désordonnés, parce qu'issus de filtres de recherches "complexes" tels que "rechercher toutes les images dans toutes les sous-categories (<- récursif) de ImagesCategory.find(1337)".

Eh bien oui il faut réordonner tout cela, et c'est pour ça que reorder_results existe. Cette méthode permet d'ordonner les résultats par n'importe quoi, leur identifiant par défaut, et permet de les ordonner dans le sens inverse.

Exemple :

reorder_results(a_classer, :title, true)

... ordonnera par titre et inversera l'ordre des résultats.

Le code commenté

Une fois n'est pas coutume, je vais décomposer et commenter mon code :

- Déclaration de la méthode, un argument obligatoire, deux facultatifs avec :id et false comme valeurs par défault

 def reorder_results(result, by = :id, reverse = false)

- Pour chaque élément de result :
- On met la valeur du champ line.send(by) (Voir Object#send) par lequel on veut trier dans la variable line_by, sauf si cette valeur est nil (ce qui arrive uniquement quand le champ SQL est à NULL)
- Retourne la valeur de line_by
- Applique un Array#sort sur la liste de résultats retourné, ce qui classe tous les objets comparables : String, Integer, Float et Time sont les seuls suceptibles de contenir la valeur d'un champ SQL par ActiveRecord.
- Met le tout dans determinants

   determinants = result.map {|line| 
     line_by = line.send(by).nil? ? '' : line.send(by)
     line_by
   }.sort

- Comme ça se lit : Inverse l'ordre de l'array determinants à moins que reverse soit égal à false

   determinants.reverse! unless reverse == false

- Prends l'array des résultats passés
- Selectionne son premier élement
- Selectionne sa Classe
- Met cette dernière dans object

   object = result.first.class

- Crée un array vide

   ordered = []

- Pour chaque element de determinants :
- On passe à l'object (object) "l'argument" find_by_(la-variable-by) que l'on converti en Symbol à qui l'on envoie "l'argument" determinant
- Donc, si l'objet était un Image et by valait :age, avec determinant = 17, par exemple, ce se situe après "<<" serait équivalent à : Image.find_by_age(17)
- Avec '<<', l'on ajoute ce résultat (un Image donc) à l'array ordered

   determinants.each do |determinant|
     ordered << object.send("find_by_#{by}".to_sym, determinant)
   end

- On renvoie la variable ordered

   ordered

- Fin (ouf)

 end

... ce qui donne si l'on reprends tout :

 def reorder_results(result, by = :id, reverse = false)
   determinants = result.map {|line| 
     line_by = line.send(by).nil? ? '' : line.send(by)
     line_by
   }.sort
   determinants.reverse! unless reverse == false
   
   object = result.first.class
   ordered = []
   determinants.each do |determinant|
     ordered << object.send("find_by_#{by}".to_sym, determinant)
   end
   ordered
 end

Améliorer la classe Array

Ah oui, c'est effectivement ce que j'ai dit au tout début de ce billet...
Je voulais dire par là que l'on pourrait surcharger la classe Array (ce qui n'a rien de tordu en soi) en lui rajoutant cette méthode (un peu modifiée pour que ça passe), ainsi, l'on pourrait faire quelquechose comme my_reordered_array = my_disordered_array_of_AR_results.reorder_results(:title).

Vite, du coca, je crève de soif.

Pages: