Entropie anthropique

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

lundi 26 mai 2008

Imbriquer les templates ERB "à la :render chez rails"

Parfois on a envie de pouvoir profiter du templating ERB fourni dans Ruby pour se faire des bouts de codes, ou pour toutes autres raisons, toutefois, pour ceux que ça intéresse, je les laisse évaluer un template.run dans un autre template ERB pour voir le résultat. Pour s'en sortir, il va falloir utiliser les bindings Ruby. Il y a peut-être une autre façon de faire avec les obscurs "_erbout", mais il y a peu de documentation là dessus. Aussi, devant le défi et le travail sur les bindings, je me suis laissé tenté.

A noter que pour certains j'aurai l'impression de réinventer la roue, je ne suis pas allé vérifier dans la touffe de code de Rails s'ils utilisaient la même technique.

Tout d'abord, et car j'ai la flemme de faire un bel article avec toutes les étapes qui m'ont conduit à cette solution, il n'y aura qu'un gros bloc de code avec la classe et l'exemple (certains auront l'habitude). La classe est nommée Renderer et je n'ai défini que des méthodes de classe. On pourrait faire autrement avec des instances d'une classe, mais bon, ça ne me semble pas le point essentiel.

Le point essentiel est le binding dans Ruby. Un binding, c'est une référence au contexte d'éxecution d'un bout de code. Ainsi, passer un binding permet d'avoir accès à un contexte d'éxécution autre que le langage seul le permet. C'est ce qu'on passe à ERB pour qu'il sache à quoi correspond quel nom de variable, même si le fichier est évalué dans un objet différent.

Le but étant de passer dans un Hash le nom des variables de l'intérieur du template, et de les convertir en ce qui est pointé par la clé, on sent déjà venir le eval. Pour faire simple je veux pouvoir utiliser un sous-template dans mon template en faisant

<%= render(:template_1,{'x' => 42}) %>

Je vais donc itérer sur les élements du hash, la clé me servira de variable à déclarer, et la valeur sera justement la valeur pointée. Je dois en outre éviter de déclarer une variable qui écraserait, soit une méthode, soit une variable de mon algorithme de transformation lui même (ce serait la catastrophe). Pour rendre cette probabilité plus faible, j'ai donc utilisé des underscores, vu que je serai le seul à utiliser mon système de templates, je sais la convention qui est ne pas définir une variable "__trucmuche__" dans les paramètres.

L'élément binding me permet de pouvoir itérer à l'intérieur du hash, et de faire mes eval dans le bloc passé à each et en faisant survivre hors du bloc les valeurs créées par eval.

Après ces mises en garde, je dois ajouter que j'aurai pu faire des tests et générer une exception, mais pour laisser l'importance à l'algorithme, je ne l'ai pas fait. De même, j'ai effectué un appel à eval par paire clé/valeur, mais on aurait pu faire un seul appel en créant une chaîne plus longue (et limitant un peu plus les effets de bords des écrasements de variables)

Pour finir, l'évaluation d'un template ERB se fera avec le binding passé à eval. C'est à dire qu'en cas de valeur manquante, l'interpréteur ruby cherchera une méthode et lévera une erreur. Je définis donc method_missing afin d'éviter le carnage si d'aventure on veut pouvoir rendre optionnel une des variables du template.

Bon, j'espère ne pas vous avoir assommé. Voici le code, comme d'hab questionnez si vous le voulez. En tout cas je n'ai pas cherché à savoir ce que donnerait un template qui sortirai du code à son tour interprétable par ERB, pour générer un template de template de template de ... (je doute que ça marche "out of the box")

require 'erb'

class Renderer
    @@partials = {}

    def self.add_partial(name,str="")
        @@partials[name] = str
    end
  
    def self.render(__name__,__params__=nil)
        __b__ = binding
        __params__.each_key do |k|
            __str__ = %{#{k} = __params__['#{k}']}
            puts __str__ if $DEBUG
            eval  __str__ , __b__
        end
        ERB.new(@@partials[__name__]).result __b__
    end

    def self.method_missing(m,*args)
        puts "missing params or method: #{m}, nil-ed out" if $DEBUG
        nil
    end
end

#simple example
t1 = %q{
    str1 : <%= x %>
}

#calling another partial in a partial
t2 = %q{
str2:
<% values.each do |value| %>
    <%= render(:first,{'x' => value})%>
<% end %>
}

#now test missing functions
t3 = %q{
<%= str.class %>
<% unless params.nil? %>
    there are some params
<% end %>
}

Renderer.add_partial(:first , t1)
Renderer.add_partial(:second, t2)
Renderer.add_partial(:third , t3)

puts Renderer.render(:first , {'x'=>0})
puts Renderer.render(:second, {'values'=>(0 .. 10)})
puts Renderer.render(:third , {'str'=>Array.new})
puts Renderer.render(:third , {'str'=> "ok", 'params'=>Array.new})

samedi 24 mai 2008

Wmii moi itou

Bon, et bien, dans ma quête du tuning de distribution, j'ai essayé Wmii, les concepts de design correspondent mieux à ce dont j'ai besoin que les mamouths du window management, à savoir: des fenêtres qui prennent toute la place, quand elles en ont besoin seulement, pilotable au clavier et facilement scriptable.

Par exemple, pour voir combien de jus il reste dans la batterie, plutôt que de regarder l'uptime, j'utilise

echo -n $(cat /proc/acpi/battery/BAT1/state | grep remaining | sed 's/.*:\s*//') '|' $(date)

à l'intérieur de la fonction status() .

dimanche 18 mai 2008

Evaluation des arguments multiples et des blocs avec l'héritage en Ruby

Ça me servira à la fois de piqûre de rappel quand j'en aurais besoin, et ça peut aider à éclaircir les idées. On oubliera pas de ne pas oublier (oui oui, tout ça, j'insiste) que l'appel à super récupère lui-même le bloc. Ce peut être gênant si on a besoin de faire un yield dans la classe fille en même temps qu'on a besoin d'appeler super. Ceci rend plus difficile le changement de comportement d'une méthode qui detruit des informations quand on lui passe un bloc (par exemple l'ouverture/fermeture automatique des fichiers) : il faut faire son yield à l'intérieur d'un nouveau bloc, selon ce qui passe dans les paramètres du bloc ça peut être plus ou moins facile.

Au niveau des arguments multiples, on oubliera pas de ne pas oublier la différence entre *args et args. Il faut voir ça comme un pointeur sur un objet Array. Également, la classe d'un objet, même quand dans la méthode parente est celle de l'objet hérité, ça pourrait jouer des tours si on fait des tests avec == au lieu de is_a? (je n'ai pas mis dans le test, mais is_a? teste l'appartenance d'un objet à une classe et toutes les classes parentes.

Voici le code qui m'a servit pour tout mettre au clair :

class Test
    def initialize(*args,&block)
        puts args.size
        puts self.class
        yield self if block_given?
    end
end

class SubTest < Test
    def initialize(*args)
        super(*args)
        yield self if block_given?
    end
end

class SubSubTest < SubTest
    def initialize
        super(:un,:dos,:tres) {|l| puts "truc"}
        yield self if block_given?
    end
end

class SubSubSubTest < SubSubTest
    def initialize
        super() do |l|
                puts "sub-truc"
                yield self
        end
    end
end

Test.new(1,2) {|l| puts l.class}
SubTest.new {|l| puts l.class}
SubSubTest.new {|l| puts l.class}
SubSubSubTest.new {|l| puts l.class}

Et voici le résultat brut de décoffrage :

2
Test
Test
0
SubTest
SubTest
SubTest
3
SubSubTest
truc
truc
SubSubTest
3
SubSubSubTest
truc
truc
sub-truc
SubSubSubTest

On notera que le "puts self.class" dans la classe principale rajoute une occurence du texte, j'aurais pû mettre ici (ou équivalent plus bas dans la hierarchie) un "if self.class == Test" ou un "if self.is_a? Test" pour montrer la différence entre les deux.

Si vous avez des questions, questionnez, mais je ne promets rien pour les réponses.

lundi 5 mai 2008

Fin de la publicité sur les chaînes publiques

On sait déjà qui veut sa part du gâteau: Laurent Petitgirard de la SACEM Quelqu'un pour le SNEP D'autres pour la SACD Je sens que comme à la radio, les programmations vont être répétitives et iront enfler les poches de ceux qui n'en ont pas besoin.

Je vous suggère de lire "Le chien qui porte à son cou le dîner de son maître", et vous laisse méditer sur les communiqués précédents.

samedi 3 mai 2008

Ubun-tue

J'ai voulu tester les capacités de la si renommée Ubuntu, du coup je l'utilise depuis environ deux mois. Voici mes impressions.

  • l'installation m'avait parue longue pour ce que c'était, charger un live-cd pour ensuite installer, pourquoi pas mais c'est pas ce qui me serait venu à l'esprit
  • certains paramètrages par défaut étaient invivables, par exemple le driver Synaptics : impossible à configurer correctement (j'ai du le désactiver en éditant le xorg.conf à la main)
  • la carte son n'était pas reconnue dès le départ, sans raison particulière car il "suffit" d'éditer une configuration alsa (à la main)
  • après un mois, un mois et demi d'usage, les fenêtres s'ouvrent systématiquement en plein écran, alors que je voudrais qu'elles s'ouvrent comme on les a laissées. Impossible de trouver ou configurer ça dans l'ignoble Gnome, je suis arrivé à modifier ce comportement pour Nautilus seulement, en éditant la base de registre Gconf. Malgré tout, le settings a quand même sauté.
  • si on active les "effets jolis" de compiz-fusion, alors le terminal clignote dès qu'il signale une "erreur", c'est à dire qu'il devient invivable d'utiliser Vim dans un terminal (par exemple): si on fait echap une fois de trop le machin vous arrache les yeux, il "suffit" d'installer l'application d'édition des effets de compiz et de trouver la bonne case (je vous laisse chercher)
  • le packaging à la debian qui sépare toujours en 12000 paquets un logiciel, ses headers etc. font que pour compiler un truc, il faut chercher quinze ans les bons headers, mais ça ce doit être une question de goût, perso je pense que la place occupée par les headers etc. est négligeable pour le public visé par Ubuntu et pourraient être livrés avec
  • finalement, mise à jour laborieuse avec la nouvelle version "support à long terme", les settings ont encore sauté, les touches du clavier pour changer le volume ne marchent plus (il y a bien le pop-up carré avec le volume qui s'affiche, mais la barre de volume reste figée), les bips systèmes ont été restaurés, le fuseau horaire a sauté également
  • sans compter les nouvelles applications plus beugguées que les anciennes (au pif, l'aperçu des espaces de travail qui montrent des fenêtres inexistantes), merci le choix des packages
  • les outils d'administrations me laissent perplexe, par exemple l'outil réseau sert à quoi et à qui ? pourquoi on a "scan de ports" dans un cas et "traceroute" dans l'autre, il n'y a aucune cohérence, dans le choix des noms et le placement de ces outils. D'ailleurs ça sert à quoi au lambda, aux "êtres humains" (car Ubuntu c'est Linux for human beings) ? à priori à rien, et pour ceux qui ont besoin de scanner leur réseau, bah en général ils utilisent nmap car on y met les options qu'on veut.

En conclusion, Ubuntu me laisse une impression d'avoir un système qui tourne mais impossible à configurer, tout du moins sans ligne de commande. C'est en contradiction avec la publicité qu'en font ses fan-boys. Pour avoir déjà utilisé OpenSuse ou Mandrake (c'était pas encore Mandriva), j'dois dire qu'Ubuntu est encore loin derrière les standards d'il y a deux ou trois ans. En tout cas je ne la recommanderai pas à un débutant, et non plus à un développeur. A la limite KUbuntu ou XUbuntu (donc sans Gnome) pourrait être moins pire, mais ne comptez pas sur moi pour faire le test. D'ici la fin du mois, Ubuntu giclera. Ça tombe bien, la nouvelle Slackware est sortie, et je dois aussi tester ArchLinux et Frugalware.

Oui, Ubuntu "just works", c'est à dire qu'il marche à peine.

vendredi 2 mai 2008

Kylie Minogue décorée par Albanel

Et oui, Lundi 5 Mai 2008, Kylie Minogue recevra l'insigne de "Chevalier dans l'ordre des Arts et des Lettres". Consécutivement à d'autres artistes émanants de l'industrie pure et dure (Bob Dylan, Meryl Streep et Uma Thurman). A quand Madonna ou Britney Spears pour leur passion des enfants? Bienvenue à la Cour.

http://news.bbc.co.uk/2/hi/entertainment/7380789.stm http://www.culture.gouv.fr/culture/actualites/index.htm

jeudi 1 mai 2008

Les mots les plus fréquents sur le RSS de l'Assemblée Nationale

Merci Hpricot :) . En virant les mots un peu inutiles car n'apportant pas d'information, sachant que "de" est le grand gagnant, avec une fréquence de cinq pourcents (mais je n'ai pas fais la somme des le/la/l' qui doivent se valoir). Les mots les plus utilisés ces derniers temps à l'Assemblée Nationale sont (suivis de leur fréquence, et sans tri):

--- - - "ADOPT\xC9"

 - 0.000682860208760121

- - "ASSEMBL\xC9E"

 - 0.000780411667154424

- - NATIONALE

 - 0.000780411667154424

- - relatif

 - 0.000585308750365818

- - lutte

 - 0.000877963125548727

- - contre

 - 0.00117061750073164

- - produits

 - 0.000682860208760121

- - "Assembl\xE9e"

 - 0.000682860208760121

- - nationale

 - 0.00097551458394303

- - projet

 - 0.000780411667154424

- - loi

 - 0.00351185250219491

- - article

 - 0.0130718954248366

- - code

 - 0.00614574187884109

- - "r\xE9dig\xE9"

 - 0.00282899229343479

- - application

 - 0.00136572041752024

- - usage

 - 0.000682860208760121

- - personnel

 - 0.000780411667154424

- - notamment

 - 0.000585308750365818

- - substances

 - 0.00136572041752024

- - "proc\xE9d\xE9s"

 - 0.00146327187591454

- - "mentionn\xE9s"

 - 0.00146327187591454

- - conditions

 - 0.00302409521022339

- - lorsque

 - 0.000585308750365818

- - "pr\xE9sent"

 - 0.00097551458394303

- - convention

 - 0.00107306604233733

- - dopage

 - 0.000877963125548727

- - Paris

 - 0.000682860208760121

- - accord

 - 0.00146327187591454

- - personne

 - 0.00165837479270315

- - moyen

 - 0.000585308750365818

- - "contr\xF4le"

 - 0.000585308750365818

- - "pr\xE9vues"

 - 0.00136572041752024

- - titre

 - 0.00214613208467467

- - dernier

 - 0.00136572041752024

- - "alin\xE9a"

 - 0.00380450687737782

- - "modifi\xE9"

 - 0.00146327187591454

- - "Apr\xE8s"

 - 0.000682860208760121

- - "premi\xE8re"

 - 0.00107306604233733

- - phrase

 - 0.00107306604233733

- - "ins\xE9r\xE9"

 - 0.000682860208760121

- - "r\xE9dig\xE9e"

 - 0.000585308750365818

- - "d\xE9lai"

 - 0.0031216466686177

- - "deuxi\xE8me"

 - 0.00126816895912594

- - "apr\xE8s"

 - 0.00204858062628036

- - mot

 - 0.00126816895912594

- - "ins\xE9r\xE9s"

 - 0.00107306604233733

- - mots

 - 0.00409716125256073

- - sous

 - 0.00097551458394303

- - peine

 - 0.000682860208760121

- - "remplac\xE9s"

 - 0.00156082333430885

- - "op\xE9rations"

 - 0.000682860208760121

- - "acc\xE8s"

 - 0.000780411667154424

- - judiciaire

 - 0.000585308750365818

- - agents

 - 0.00097551458394303

- - relevant

 - 0.000585308750365818

- - "charg\xE9"

 - 0.000780411667154424

- - personnes

 - 0.00136572041752024

- - peuvent

 - 0.00117061750073164

- - documents

 - 0.0034143010438006

- - dispositions

 - 0.00253633791825188

- - chapitre

 - 0.00156082333430885

- - autorisation

 - 0.000585308750365818

- - ordonnance

 - 0.00165837479270315

- - "\xE9l\xE9ments"

 - 0.000585308750365818

- - demande

 - 0.00097551458394303

- - publique

 - 0.00126816895912594

- - "autorit\xE9"

 - 0.000877963125548727

- - date

 - 0.00224368354306897

- - livre

 - 0.00146327187591454

- - "int\xE9ress\xE9"

 - 0.000585308750365818

- - suivant

 - 0.000682860208760121

- - lorsqu&

 - 0.000585308750365818

- - premier

 - 0.00136572041752024

- - punie

 - 0.000682860208760121

- - ans

 - 0.00224368354306897

- - emprisonnement

 - 0.00107306604233733

- - amende

 - 0.00107306604233733

- - "r\xE9f\xE9rence"

 - 0.00146327187591454

- - "r\xE9f\xE9rences"

 - 0.000585308750365818

- - articles

 - 0.00146327187591454

- - "compl\xE9t\xE9"

 - 0.000780411667154424

- - "pr\xE9sente"

 - 0.00156082333430885

- - section

 - 0.00126816895912594

- - partie

 - 0.00156082333430885

- - "mati\xE8re"

 - 0.000682860208760121

- - Gouvernement

 - 0.000682860208760121

- - compter

 - 0.00175592625109745

- - publication

 - 0.00117061750073164

- - droit

 - 0.00107306604233733

- - Parlement

 - 0.000682860208760121

- - Conseil

 - 0.00097551458394303

- - entre

 - 0.000780411667154424

- - juillet

 - 0.000682860208760121

- - portant

 - 0.000877963125548727

- - devant

 - 0.000585308750365818

- - jour

 - 0.000585308750365818

- - archives

 - 0.00380450687737782

- - patrimoine

 - 0.000585308750365818

- - publiques

 - 0.00107306604233733

- - "collectivit\xE9s"

 - 0.000585308750365818

- - territoriales

 - 0.000585308750365818

- - Conforme

 - 0.000585308750365818

- - issue

 - 0.000585308750365818

- - service

 - 0.000682860208760121

- - public

 - 0.000585308750365818

- - "fix\xE9es"

 - 0.000682860208760121

- - conservation

 - 0.000780411667154424

- - "s\xE9curit\xE9"

 - 0.000585308750365818

- - communication

 - 0.00117061750073164

- - contrat

 - 0.00370695541898351

- - contrats

 - 0.00117061750073164

- - document

 - 0.000780411667154424

- - porte

 - 0.000682860208760121

- - atteinte

 - 0.000682860208760121

- - secret

 - 0.00107306604233733

- - cause

 - 0.000585308750365818

- - parties

 - 0.000877963125548727

- - "r\xE9serve"

 - 0.000585308750365818

- - travail

 - 0.00487757291971515

- - "dur\xE9e"

 - 0.00214613208467467

- - "ind\xE9termin\xE9e"

 - 0.000585308750365818

- - entreprise

 - 0.00126816895912594

- - employeur

 - 0.00126816895912594

- - appel

 - 0.000585308750365818

- - "ann\xE9e"

 - 0.000780411667154424

- - "d\xE9termin\xE9e"

 - 0.000877963125548727

- - conclus

 - 0.000585308750365818

- - "p\xE9riode"

 - 0.00136572041752024

- - essai

 - 0.00117061750073164

- - "salari\xE9"

 - 0.00214613208467467

- - branche

 - 0.000780411667154424

- - "dur\xE9es"

 - 0.000585308750365818

- - "indemnit\xE9"

 - 0.000682860208760121

- - rupture

 - 0.00185347770949176

- - conventionnelle

 - 0.000877963125548727

- - homologation

 - 0.000682860208760121

- - portage

 - 0.000585308750365818

Mon code était en premier jet, c'est perfectible et ce sera amélioré par la suite (il faudra sans doute rajouter un stemmer-like pour les pluriels). Les caractères bizarres font suite à un soucis d'encodage avec le langage Ruby, mais ce sont des caractères accentués, je n'ai pas pris la peine de corriger cela. On remarquera que les dopage, l'emploi et les archives ont été à l'honneur cette semaine.