Articles

1. Ruby et Rails

Pas question ici de reprendre tous les excellents tutoriels qu'on peut trouver sur l'internet, mais de donner des références et quelques conseils pour démarrer.

2. Ruby, les booléens et les comparaisons

Comme tous les langages de programmation, Ruby utilisent des variables booléennes pour évaluer la véracité des expressions, notamment dans les instructions conditionnelles comme if, while... Ruby a toutefois sa propre logique qu'il faut connaitre pour en tirer parti et pour éviter les erreurs, il a aussi son propre dialecte qui simplifie les écritures.

3. Le langage de vues HAML

Plus concis que ERB, le langage HAML permet d'écrire un code clair pour les vues et les composants.

Kit du Aioeur

1. Ruby et Rails

Pas question ici de reprendre tous les excellents tutoriels qu'on peut trouver sur l'internet, mais de donner des références et quelques conseils pour démarrer.

Pour gérer le code de l'application, je n'ai rien trouver de mieux que Notepad++ qui sait colorer les formats des langages utilisés par Ruby onRails.


1. Ruby

Ruby est un langage objet moderne et souple, pratique pour les programmeurs, facile à prendre en main à partie de la connaissance d'un autre langage, mais avec des fonctionnalités uniques. À travers Rails, le langage Ruby est peu visible, mais il est profitable de savoir bien l'utiliser.

Le langage est interprété en développement, mais le code compilé sera mis en cache en production.

Les variables ne doivent pas être déclarée et ne sont pas typées, mais les données qu'elles contiennent le sont.

La classe Hash gère des tableaux de couples (clé - valeur) qui donne beaucoup de souplesse aux listes indéfinies, notamment aux paramètres d'appel des fonction.

Affectations multiples :
a = b = 3 → 3 est copié dans a et dans b
a, b = 1, 2 → équivalent à a = 1 ; b = 2
a, b = [1, 2] → les éléments du tableau sont ventilés dans les variables de gauche
a, b, c = 1..3 → équivalent à a = 1 ; b = 2 ; c = 3 : les valeurs de l'intervalle 1..3 sont ventilés dans les variables de gauche

Les blocs de code, les méthodes, les classes sont considérés comme des données qui peuvent faire l'objet de traitement.

Le code est dynamiquement extensible. Par exemple, tous les appels vers une méthode non définie sont routées vers la méthode method_missing qui peut analyser l'appel et générer une réponse en fonction du contexte. Les classes de gestioon des données de Rails traient ainsi toutes les fonction de recharche par attributs du type find_by_name ou même find_by_first_name_and_last_name.

Une classe peut toujours être ré-ouverte pour la modifier ou la compléter, y compris les classes standard.

Les modules permettent des héritages multiples.

Un mode console : après l'installation de Ruby sur votre machine, ouvrir une fenêtre et taper irb (interactive ruby) - ou par SSH sur une machine distante.

etc.

1.1. Références

En ligne

1.2. Contexte AIO

Le développement du logiciel projet_a est réalisé avec Ruby 1.9.3, sous Windows NT pour cause d'indisponibilité des bons pilotes d'écrans sous Linux. Quelques tests sont effectués sur une Ubuntu gérée par VM virtual Box.

À cause de la version courante de cPanel, les serveurs o2switch sont bloqués à la version 1.8.7 de Ruby (commande ruby -v). L'objectif est de passer au plus tôt la plate-forme de production sous Ruby 1.9.3.

L'utilitaire RVM permet d'installer plusieurs versions de Ruby dans l'espace privé d'un utilisateur Linux. Il n'est pas encore opérationnel sur a-io.eu, sans doute pour cause de variables d'environnement non ou mal renseignées.

1.3. Compatibilité Ruby 1.8 - Ruby 1.9

Voici quelques simples écarts entre les versions 1.8 et 1.9 de Ruby à connaitre pour obtenir un code compatible entre les deux versions.

Pliage des lignes de code
Ruby 1.9 est plus souple sur les contraintes imposées au pliage des longues lignes de code.
Écrire : le symbole en fin de ligne. Exemples

a > b ?
  nil : a + b

a + b +
      c
 fonction(
  argument)

Extrait d'un caractère d'une chaine
Chaine[i] retourne le (i+1)ème caractère de Chaine en type Integer avec Ruby 1.8, en type String avec Ruby 1.9.
Écrire : Chaine[i..i] = intervalle entre i et i, ou mieux : Chaine[i, 1]  = 1 caractère à partir de i.

Nouvelles notations
Ruby 1.9 introduit de nouvelles notations plus agréables qu'on évitera si on veut garder la compatibilité avec la version 1.8.
Écrire : { :a => 2 }, pas { a: 2 } (class Hash)

Tri
Les hachages (class Hash) respectent l'ordre de création des éléments en Ruby 1.9, pas en 1.8.
Écrire : une fonction de tri quand c'est possible... ou attendre la migration complète vers Ruby 1.9 (solution choisie pour projet-a).


2. Ruby on Rails

Ruby on Rails, alias Rails ou RoR pour les intimes.

2.1. Références

En français (pas tout)

2.2. Contexte AIO

Le logiciel projet_a est développé avec la version 3.0.15 de Rails. Une adaptation est sans doute nécessaire pour la gestion des ressources (assets) qui a notablement évolué avec la version 3.1.

version 0.8.2-0222-120824

Kit du Aioeur

2. Ruby, les booléens et les comparaisons

+ les expressions conditionnelles et les boucles

Comme tous les langages de programmation, Ruby utilisent des variables booléennes pour évaluer la véracité des expressions, notamment dans les instructions conditionnelles comme if, while...
Ruby a toutefois sa propre logique qu'il faut connaitre pour en tirer parti et pour éviter les erreurs, il a aussi son propre dialecte qui simplifie les écritures.

1. Classes et valeurs  booléennes

Ruby ne comporte pas une classe pour les valeurs booléennes, mais trois : TrueClass, FalseClass et NilClass. Chacune comprend une et une seule valeur prédéfinie, respectivement: true, false et nil.

1.1. Valeur nil

Sémantiquement, la valeur nil signifie que l'élément associé n'est pas définie.

Il est possible de transformer la valeur nil en l'élément neutre des ensembles de valeurs des classes usuelles :

  • nil.to_a → [] tableau vide
  • nil.to_i → 0 nombre entier nul
  • nil.to_f → 0.0 nombre flottant nul
  • nil.to_s → "" chaine vide

Tout objet possède la méthode nil? qui permet de tester si un élément a une valeur définie ou non, c'est-à-dire est égale à nil ou à tout autre chose.

Rails définit aussi sur les objets des méthodes qui analysent le contenu :

  • blank? qui est vraie si l'élément est blanc ou vide, donc de valeur égale à nil, une chaine vide ou blanche, un tableau ou un hash vide ;
  • present? qui est la fonction opposée, donc fausse dans les mêmes cas.

NB : Même pour prendre la valeur nil, une variable doit être définie. On peut tester cette situation avec la fonction defined? décrite au chapitre suivant.

1.2. Valeur booléenne d'une variable

Les valeurs false et nil sont considérées comme fausses.
Toutes les autres valeurs, y compris 0 (zéro), "" (chaine vide), [] (tableau vide, etc., sont considérées comme vraies.

2. Expressions booléennes

Ruby disposent des trois fonctions booléennes de base - et, ou et non -, chacune en plusieurs versions, subtilement différentes :

  • fonction et → && and &
  • fonction ou → || or &
  • fonction ou exclusif → ^
  • fonction non → ! not

2.1. Différences entre les opérateurs booléens

Les différences entre les différentes formes sont les suivantes :

  1. &&, and, ||, or, !, not peuvent avoir les membres de l'expression de tous types ;
    &, |, ^ doivent avoir les deux membres de l'expression de l'une de trois classes booléennes énoncées au chapitre 1 pour être interprétés comme des opérateurs booléens. Ces trois opérateurs peuvent en effet avoir des comportements spécifiques pour certaines classes (ex. : intersection et union de tableaux, opérateurs bit à bit pour les nombres entiers).

  2. &&, and, ||, or évaluent le premier membre de l'expression et uniquement si nécessaire le second ;
    & et | évaluent toujours les deux membres de l'expression.
    La différence tient aux effets de bord potentiel si le deuxième membre contient une affectation ou l'appel d'une fonction qui modifie une variable.

  3. && et || renvoient le dernier membre utile et évalué d'une expression, pas sa valeur booléenne. Ex. : 'abc' || nil → 'abc' ;
    &, |, ! et not renvoient toujours une valeur booléenne (true ou false). Ex. : 'abc' | nil → true.

  4. La précédence de tous ces opérateurs, c'est-à-dire l'ordre dans lequel ils sont évalués dans une expression complexe, sont différentes (voir le tableau des précédences) ;

  5. !, &, | sont des méthodes qui peuvent être redéfinies pour chaque classe (ou pour toutes si elles sont définies sur la classe mère Object) ;
    tous les autres opérateurs ne peuvent pas être redéfinis.

Conseil : Sauf besoins particuliers et à vos risques et périls, limitez-vous aux trois opérateurs &&, || et !, et placez des parenthèses dans les expressions complexes !

2.2. Operateur defined?

On peut classer l'opérateur defined? parmi les opérateurs booléens, car il est parfois bien utile dans les expressions conditionnelles pour éviter les erreurs impromptues, notamment pour vérifier l'existence de variables de classes ou de paramètres de partiels.

defined?(x) vaut nil si x n'est pas défini. S'il l'est, alors defined?(x) vaut une chaine de caractères relative à la nature de x.
Dans une expression booléenne, defined?(x) peut donc être considérée comme vraie si x est défini, fausse sinon.

NB : Comme en Ruby "tout est objet", defined? peut être utilisé pour vérifier l'existance d'une méthode, d'une classe ou d'un module.

2.3. Méthode nil?

La classe Object contient la méthode nil? qui vérifie si un objet prend la valeur nil. Elle rend la valeur true dans ce cas, false sinon.

Quand on est certain du type de la valeur potentielle d'une variable et qu'elle ne peut prendre la valeur false, on peut utiliser cette variable dans une expression conditionnelle comme négation de nil?.
Exemple : if x est dans ce cas similaire à unless x.nil? (lui même équivalent à if !x.nil? - voir le chapitre 5.).
Le risque est une potentielle valeur false. On évitera donc cette forme, ntamment pour tester des paramètres d'appel.

3. Affectations

Les auto-affectations ||= et &&= tirent parti des propiétés 1, 2 et 3 du chapitre 2.1 pour la forme dialectique suivante :

param ||= default permet d'assigner à la variable param la valeur de default si param n'est pas vrai, c'est-à-dire si elle n'est pas définie et si elle ne prend pas l'une des valeurs nil ou false. À noter qu'après cette instruction, param sera toujours définie, éventuellement à nil ou false suivant la valeur de default.

param &&= nouveau est beaucoup moins fréquent. Cette forme permet de remplacer la valeur de param par celle de nouveau uniquement si param est défini par autre chose que nil ou false. Là aussi, après cette instruction param sera toujours définie et contiendra nil si l'affectation a échoué.

Ces formes peuvent être étendues. Par exemple :

param ||= default1 || default2 : si param n'est pas définie ou vaut nil ou false, lui affecter la valeur de default1 ; si celle-ci vaut nil ou false, lui affecter alors la valeur de default2.

On peut aussi trouver dans une boucle l'expression :

(params ||= []) << param : si params n'est pas définie, l'initialiser avec un tableau vide, puis dans tous les cas y ajouter la valeur de param. L'initialisation du tableau aurait dû être réalisée en dehors de la boucle ou par une instruction conditionnelle complexe.

4. Opérateurs de comparaison

Ruby connait dix opérateurs de comparaison : ==   ===   <=>   <   <=   >   >=   =~   !=   !~ 

==   <   <=   >   >= sont les opérateurs de comparaison habituels.
Tous retournent toujours l'une des deux valeurs booléennes true ou false.

=== est utilisé dans l'instruction case target when à la place de ==. Il s'agit la plupart du temps de la même méthode.
Il retourne toujours l'une des deux valeurs booléennes true ou false.

<=> est utilisé notamment pour les tris des objets d'une classe.
Il retourne en général -1, 0 ou 1 ; ce n'est donc pas un opérateur booléen, car ces trois valeurs sont associées à la valeur true.

=~ teste une chaine à une expression régulière.
Il retourne nil si la chaine ne respecte pas l'expression régulière, sinon l'indice du premier caractère où celle-ci est vérifiée. Ces valeurs sont transposées respectivement dans les valeurs false et true.

!=   !~ sont les négations de == et de =~ .
Contrairement aux autres opérateurs, ce ne sont pas des méthodes ; ils ne peuvent donc pas être redéfinis.
a != b est équivalent à !(a == b), et a !~ b est équivlent à !(a =~ b).
Les deux opérateurs retournent toujours l'une des deux valeurs booléennes true ou false.

5. Expressions conditionnelles

Les expressions booléennes sont le plus souvent utilisées dans les expressions conditionnelles.

En Ruby, toutes les expressions renvoient une valeur. Elles peuvent donc intervenir dans des expressions plus complexes, comme des affectations.
Exemple : html = '<h1>' + (if page == 1 then 'Première' else 'Autre' end) + ' page</h1>'

5.1. Expressions if et unless

Syntaxe de l'expression if :

if condition [ then ]
   body
[ elsif condition [ then ]
   body , ... ]
[ else
   body ]
end

Syntaxe de l'expression unless :

unless condition [ then ]
   body
[ else
   body ]
end

unless est l'opposé de if : unless condition est équivalent à if !condition.

Le mot-clé then n'est obligatoire que si la clause suivant est sur la même ligne.

Modificateurs if et else :

if et unless peuvent être aussi utiliser comme des modificateurs sous l'une des deux formes, très fréquentes quand il n'y a pas de partie alternative elsif ou else :

instruction if condition
instruction unless condition

L'instruction n'est évaluée que si la condition est respectivement vraie ou fausse.

NB : Si l'instruction modifiée est une affectation, la ou les variables à gauche du signe égal (=) seront définies et initialisées à la valeur nil si elle n'étaient pas définies avant. Ce comportement est général et s'applique aussi en particulier aux affectations internes des expressions conditionnelles.

Une expression conditionnelle retournera nil si la condition n'est pas remplie et si elle ne comporte pas de clause else.

5.2. Opérateur ternaire ? :

Syntaxe :    condition ? expr1 : expr2

Il est équivalent à   if condition then expr1 else expr2 end

Rien n'empêche qu'expr1 ou expr2 soient des expressions complexes commes des affectations, voire qu'elles comprennent d'autres opérateurs ternaires.

5.3. Expressions case

Il existent deux formes d'expressions case qui chacune ont leur équivalent en expression if.

La première forme enchaine plusieurs conditions :

case
when condition [, condition ]... [ then ]
   body
when condition [, condition ]... [ then ]
   body
...
[ else
   body ]
end

La seconde forme teste une expression cible à plusieurs valeurs :

case target
when comparison [, comparison ]... [ then ]
   body
when comparison [, comparison ]... [ then ]
   body
...
[ else
   body ]
end

Chaque test exécute une expression comparison === target.

Une expression testée peut être un tableau précédé d'une étoile (*) : chaque élément du tableau sera alors testé tour à tour.

Comme pour if et unless, une expression case retournera nil si la condition n'est pas remplie et si elle ne comporte pas de clause else.

6. Boucles

Les expressions booléennes servent à terminer les boucles.

En pratique, les boucles while, until et for sont assez peu utilisées, car elles sont le plus souvent remplacées par un itérateur appliqué sur un objet énumérable (un itérateur est une méthode de l'objet dont le nom commence souvent par each).
Il y a une différence notable entre ces deux types de boucles : les variables locales définies dans le corps de la boucle le restent en dehors, ce qui n'est pas le cas pour celles définies dans le bloc d'un each (ou d'un loop).

6.1. Boucles while et until

Syntaxe d'une boucle while :

while condition [ do ]
   body
end

Syntaxe d'une boucle until :

until condition [ do ]
   body
end

Modificateurs while et until :

while et until peuvent être utilisés comme modificateurs avec l'une des deux syntaxes suivantes :

expression while condition
expression until condition

6.2. Boucle for

for name [, name ]... in expression [ do ]
  body
end

Cette instruction est peu utilisée, car on lui préfère la version plus objet, presqu'équivalente :

expression.each do | name [, name ]... |
   body
end

6.3. Boucle loop

loop do
   body
end

Pour se terminer, une boucle loop doit contenir une instruction break.

loop n'est pas une instruction du langage, mais un itérateur du module Kernel. Elle est donc suivie d'un vrai bloc do end dont les variables locales sont internes.

6.4. break, redo, next et retry

break, redo, next et retry modifient le cours de l'exécution d'une boucle ou d'un itérateur.

  • break sort immédiatement de la boucle ;
  • redo recommence en début de boucle sans exécuter la condition de la boucle ;
  • retry recommence en début de boucle en exécutant la condition ;
  • next saute en fin de boucle, ce qui conduit à exécuter la condition.

break peut être suivi d'un ou plusieurs arguments qui sont retournés comme valeur de retour, sous forme d'un tableau s'il y en a plusieurs.

version 0.8.3-0226-120923

Kit du Aioeur

3. Le langage de vues HAML

Plus concis que ERB, le langage HAML permet d'écrire un code clair pour les vues et les composants.

1. Référence

Voir le site de référence http://haml.info/

L'indentation des lignes du code donne le niveau d'imbrication du code HTML ou Ruby, les blocs sont implicitement fermés.
Les lignes sont indentées par une nombre pair de caractère espace (pas de code de tabulation ! régler votre éditeur de texte en conséquence.).

Exemple :

Code HAML Code ERB équivalent
#categorie
- if @space.parent_id != @site.root_space_id
= render 'p2001_space_header'
<div id="categorie">
<% if @space.parent_id != @site.root_space_id %>
<%= render 'p2001_space_header' %>
<% end>
</div>

2. Principales instructions

%xx Balise HTML xx
#xx Identifiant id="xx" (balise <div> implicite)
.xx Attribut class="xx" (balise <div> implicite)
(attr=val) Attribut attr=val (val est une chaine ou une variable)
- xx Instruction Ruby xx (le résultat n'est pas généré en sortie)
= xx Évaluation Ruby (le résultat est généré en sortie)
-# xx Commentaire Ruby (non généré en sortie)
/xx Commentaire HTML (généré en sortie)
#{xx} Interpolation Ruby (le résultat du code est intégré à la ligne source)
:javascript Balise <script>
:css Balise <style>

Toute ligne commençant par un symbole différent ou par le caractère d'échappement '\' est reproduite en sortie.

2.1. Coupure de ligne

Terminer chaque ligne par le caractère '|'.

Ceci n'est souvent pas nécessaire si la coupure de l'instruction Ruby est régulière et si l'indentation de la ligne suite est entière (nombre pair d'espaces).

version 0.8.2-0223-120909
↑ Haut