playlist Utilisation des helpers et CSS

Publié il y a 8 mois dans la série : Rails
Nicolas Cavigneaux
Votre formateur
Nicolas Cavigneaux

A la recherche d'un langage polyvalent, j'ai fait la découverte de Ruby en 2003. J'ai donc très vite commencé à utiliser Ruby au quotidien pour des tâches diverses et variées (scripting, applications lourdes…).

Courant 2004, une vague de fraicheur est apparue avec l'arrivée de Ruby on Rails qui m'a de suite conquis. J'ai donc décidé de participer activement à la communauté (forums, patches, librairies, …). En 2010, je fais la rencontre de Martin Catty et retrouve dans sa vision la rigueur et les bonnes pratiques que j'aime mettre en place, le déclic a donc été immédiat.

Synbioz met en place des solutions robustes sur la base d'outils modernes et funs, je veux faire partie de l'aventure.

Catégories : Développement

Découvrons comment rendre notre application plus agréable visuellement en y ajoutant du CSS et en utilisant des helpers pour mieux présenter les données
Afficher le transcript complet de la vidéo
Amélioration de style du listing produits

Bienvenue dans cette vidéo consacrée à Ruby on Rails. Dans la vidéo
précédente nous avons initié une application de vente en ligne dans
laquelle nous avons mis en place la gestion des produits grâce au
scaffolding.

Aujourd'hui nous allons améliorer l'existant en ajoutant un peu de CSS
puis en utilisant des helpers fournis par Rails pour avoir une
présentation plus agréable.

Installation de bootstrap

Le moins qu'on puisse dire c'est que je ne suis pas un dieu de CSS et
de la mise en forme de manière générale. Je vais donc vous épargner un
long moment gênant de création de règles de style dédié à notre
application et utiliser Bootstrap à la place.

L'avantage c'est que nous ne perdrons pas de temps sur un aspect qui
n'est pas directement lié à l'utilisation de Rails et ça nous
permettra de voir comment installer et utiliser un paquet NPM.

Comme nous n'avons pas initialisé l'application avec l'option
`--webpack`, nous allons ajouter la gem Webpacker à la main au
`Gemfile` pour avoir une gestion transparente de Webpack dans notre
application et ainsi pouvoir utiliser ES6 et toutes les bonnes choses
que nous apporte Webpack :

# Transpile app-like JavaScript. Read more: https://github.com/rails/webpacker
gem 'webpacker'


puis on l'installe :

$ bundle install
$ bundle exec rails webpacker:install


Plusieurs choses se passent ici, de la config Webpack est générée pour
nous en fonction de l'environnement d'exécution, et ce qui nous
intéresse le plus, un nouveau répertoire `app/javascript` est créé.

Finalement la moitié du monde est installé par Yarn qui est utilisé
dans les dernières version de Rails pour installer les paquets NPM.

Ajoutons maintenant la dépendance à Bootstrap via la commande
adéquate :

$ yarn add bootstrap@4.0.0

On peut ensuite effectivement installer Bootstrap dans notre
application grâce à la tâche Rake dédiée :

$ bundle exec rake yarn:install

On peut donc installer n'importe quel paquet NPM en suivant cette
procédure et en profiter directement dans notre application Rails.

Il nous reste une dernière chose à faire pour que le code de Boostrap
soit effectivement accessible dans notre application. Il faut que nous
indiquions à webpack qu'on souhaite l'utiliser. J'ajoute donc un
fichier manifeste spécifique au CSS dans
app/javascript/packs/application.scss qui contient :

@import '~bootstrap/dist/css/bootstrap'

Passons maintenant au plus amusant, l'amélioration de nos templates !

Modification du layout application

Avant de modifier notre vue de listing, il faut apporter quelques
modifications à notre layout général pour qu'il corresponde à la
structure de base attendue par Bootstrap.

Pour que Bootstrap soit accessible à travers toute notre app, éditons
le fichier `app/views/layouts/application.html.erb` pour ajouter la
ligne suivante dans le head :

<%= stylesheet_pack_tag 'application' %>

Cette ligne sert simplement à dire à Rails « Hey j'ai un fichier
application dans mon répertoire de packs, charges le ! ».

On va également enrober notre contenu dans un conteneur pour que les
éléments soient mieux disposés :

<div class="container">
  <%= yield %>
</div>


Le mot-clé `yield` indique l'endroit où nos vues associées à une
action vont être injectées, c'est donc à cet endroit que le contenu
spécifique à une page s'affichera.

On va ensuite améliorer la présentation de notre tableau de produits en
ajoutant simplement une classe à ce dernier dans le fichier
`app/views/products/index.html.erb` :

<table class="table table-striped">

C'est déjà beaucoup plus sympa visuellement.

Continuons en modifiant les liens d'action pour qu'ils s'affichent
comme des boutons :

<td><%= link_to 'Show', product, class: "btn btn-primary" %></td>
<td><%= link_to 'Edit', edit_product_path(product), class: "btn btn-secondary" %></td>
<td><%= link_to 'Destroy', product, method: :delete, data: { confirm: 'Are you sure?' }, class: "btn btn-danger" %></td>


Ici les liens sont générés par des helpers fournis par Rails, on
doit donc leur passer le paramètre qui nous permet de définir les
classes CSS. Sans surprise on a donc ajouté le paramètre `class` qui
permet de définir les classes à appliquer aux liens.

On voit que par défaut le lien destroy contient déjà quelques
paramètres en plus.

Le premier paramètre correspond au contenu du lien, ce qu'on voit
affiché à l'écran, le deuxième est l'adresse vers laquelle pointe se
lien. Ici encore on fait appel à un helper, de route cette fois,
pour éviter de passer l'URL en dur. Le reste est en fait un seul et
même paramètre qui est un hash. Ce hash contient la méthode HTTP a
utiliser delete ici, une clé data qui permet d'ajouter des data
attributes au lien, confirm est un data-attribute spécial utilisé
par Rails pour mettre en place une confirmation javascript lors du
click sur le lien. Puis finalement nos classes CSS.

Il y a d'autres options disponibles et je vous invite à vous référer à
la doc de link_to pour en savoir plus.

Vous aurez peut-être remarqué certains liens avec un texte gris, c'est
plutôt moche, peu lisible et ce n'est pas une règle provenant de
Bootstrap. Quand nous avons fait notre scaffold dans la première
partie, Rails a créé pour nous un certain nombre de règles CSS par
défaut qu'on peut trouver dans
`app/assets/stylesheets/scaffolds.scss`. Supprimons la partie relative
aux liens :

a {
  color: #000;

  &:visited {
    color: #666;
  }

  &:hover {
    color: #fff;
    background-color: #000;
  }
}


Dans une app designée et finalisée vous ne garderez sûrement rien de
ces règles auto-générées. Concrètement on pourrait déjà tout remplacer
par des classes de Bootstrap mais ce n'est pas le but de cette vidéo.

Vous aurez noté qu'on parle de fichier SCSS, en effet, par défaut
Rails peu gérer des fichier CSS classiques mais aussi des fichiers
SCSS ou SASS qui donne plus de souplesse dans l'écriture des
règles. On a notamment accès à des variables, des imports d'autre
fichiers, des classes imbriquées etc.

Quand vous utilisez les générateurs de Rails pour créer un contrôleur,
il vous génère automatiquement plus que le fichier contrôleur. Vous
aurez le droits à un fichier javascript dédié, un fichier
CSS et également un fichier de test.

Rien ne vous oblige à les garder ou les utiliser mais c'est la façon
standard de scoper les choses dans Rails.

Utilisation des helpers

Comme je l'ai déjà mentionné, Rails met à notre disposition tout un
tas d'helpers qu'on peut utiliser pour améliorer le rendu de nos
templates et se faciliter la vie. Juste avant on a vu link_to par
exemple.

Essayons d'améliorer encore un peu le rendu de notre index en
utilisant des helpers au passage.

Nos descriptions produit peuvent potentiellement être longues, que se
passe t'il dans notre tableau si une description est très longue ?

Ce n'est pas insoutenable mais ce n'est sûrement pas idéal non
plus. Nous allons donc faire en sorte de couper cette description à
80 caractères pour que le tableau reste consistant :

<td><%= truncate product.description, length: 80 %></td>

C'est déjà mieux. Un autre cas de figure assez courant et de donner la
possibilité dans l'admin d'ajouter de l'HTML dans le contenu pour
mettre en gras, revenir à la ligne, etc.

Permettons donc d'ajouter de l'HTML. Si j'édite une description pour y
mettre un retour à la ligne que se passe t'il ?

Eh bien il ne se passe pas ce qu'on attendait, Rails pour des raison
de sécurité échappe automatiquement l'HTML qui est passé dans les
templates. Imaginez qu'un formulaire de commentaire laisse passer le
HTML sans broncher, ça serait la porte ouverte aux attaques de type
XSS. Rails fait donc le choix de tout échapper par défaut et c'est
à la charge du développeur de marquer les éléments sûrs pour qu'ils ne
soient pas échappés. Faisons ça :

<td><%= truncate product.description, length: 80, escape: false  %></td>

L'helper truncate est spécial, de part sa nature il échappe tout
son contenu pour pouvoir tronquer au caractère près. Il possède donc
une option escape à passer à false.

Si nous n'avions pas utilisé truncate, on aurait pu ajouter un appel
à raw devant la variable à afficher pour la marquer comme seine.

Il y a fort à parier qu'on se fiche du formattage dans le tableau
récapitulatif mais que ce soit plutôt sur la page de détail qu'on
veuille voir la description formattée comme attendu.

On va donc faire marche arrière dans le truncate mais on va en plus
nettoyer la chaîne de ses éventuelles balises HTML :

<td><%= truncate strip_tags(product.description), length: 80  %></td>

On a donc supprimé l'option escape et ajouter un appel à
strip_tags sur la description dont le but est de supprimer toutes
les balises d'une chaîne.

Si on vérifie, on bien l'affichage attendu, tronqué et sans balises
apparentes.

Permettons maintenant l'affichage du formattage sur la page de détail
d'un produit. Comme on le voit, par défaut l'HTML est échappé.

Éditons le fichier `app/views/products/show.html.erb` :

<%= raw @product.description %>

On a effectivement le formatage maintenant grâce à l'utilisation de
`raw`.

Passons au point d'amélioration suivant, l'affichage du prix. Comme
vous le voyez, pour le moment on a un simple nombre à virgule
flottante affiché, pas très sexy. Heureusement Rails nous propose une
fois encore un helper pour faire le travail :

<td><%= number_to_currency product.price %></td>

C'est mieux ! Mais pas satisfaisant parce qu'on voulait un prix en €
et un affichage plus classique pour un européen, à savoir avec le
sigle € à la fin et une virgule comme séparateur. On peut passer des
options à l'helper pour qu'il se conforme à nos préférences :

<td><%= number_to_currency product.price, unit: "€", separator: ",", format: "%n%u" %></td>

Et voilà qui est beaucoup mieux mais pour être tout à fait honnête ce
n'est pas la meilleure façon de faire pour arriver à se
résultat. Premièrement c'est verbeux, puis il faudrait repasser ces
options à chaque utilisation de number_to_currency. Oui on pourrait
l'enrober dans un helper maison mais ce n'est toujours pas la solution
idéal.

Par défaut, Rails se base sur la locale courante de l'application pour
choisir le formattage des prix. Toujours par défaut, une application
est configurée en anglais US. Il nous suffirait donc de changer la
locale par défaut dans la configuration de l'application et d'avoir le
fichier de traduction correspondant pour que ça soit géré
automatiquement. On pourrait aussi passer la locale à utiliser
directement à l'helper. La modification de la locale par défaut et
l'ajout des traduction dépasse le cadre de cette vidéo mais nous y
reviendrons plus tard.

Pour finir il serait quand même intéressant de pouvoir afficher les
images plutôt que de simplement afficher leur URL. Nous allons donc
ajouter des images dans le répertoire dédié à cet effet, le nom des
images devra correspondre à ce que vous avez mis dans le champs
`image_url`. Ajoutons donc les images au répertoire
`app/assets/images`.

Et maintenant passons à la modification du code pour afficher l'image
plutôt que son URL. Une fois encore Rails met à notre disposition un
helper qui sait retrouver les images dans l'arborescence et créer la
balise IMG adéquate :

<td><%= image_tag product.image_url %></td>

Pas mal, malheureusement toutes nos images n'ont pas la même taille et
le rendu n'est donc pas très joli. On va donc passer des arguments à
`image_tag` pour que toutes les images aient plus ou moins la même
taille à l'affichage :

<td><%= image_tag product.image_url, width: 50 %></td>

Voilà qui est mieux, les images ont des proportions similaires qui
facilitent la lisibilité de la liste.

Vous avez maintenant les bases nécessaires pour améliorer visuellement
et fonctionnellement votre application en ajoutant du CSS maison ou
encore en chargeant des paquets NPM pour ensuite les utiliser. Nous
n'avons qu'effleuré les helpers en en utilisant quelques uns mais
Rails en fournit beaucoup plus pour vous faciliter la vie. Je vous
invite à aller voir la documentation relatives aux helpers qui vous
permettra de découvrir d'autres outils précieux.

À bientôt dans la prochaine vidéo.
2/9 dans la sérieRails