playlist Page d'accueil et gestion de cache

Publié il y a 9 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

Cette vidéo a pour but d'expliquer comment mettre en place la page d'accueil du site et par la même occasion d'y utiliser du cache.
Afficher le transcript complet de la vidéo

Bienvenue dans cette vidéo consacrée à Ruby on Rails. 


Maintenant que nous avons le nécessaire pour gérer nos produits, il est temps de mettre en place la première page destinée au public. Cette page constituera le catalogue produit, elle va donc être sur le fond assez similaire au listing produit que nous avons mis en place via le scaffold.


Nous y mettrons un peu plus en valeur les produits puisque cette page est destinée au public et que le but est de donner envie d'acheter ces derniers.


Création de la page catalogue


Plutôt que d'utiliser le scaffolding comme précédemment et puisque nous avons déjà le modèle product à disposition, nous allons créer un nouveau contrôleur que nous allons appeler Catalog via la commande bin/rails generate controller Catalog index.


Cette commande nous crée un nouveau contrôleur ainsi qu'une vue pour l'action index. Ça nous crée également le fichier de test pour le contrôleur. Accessoirement on a aussi un fichier d'helpers ainsi que son fichier de tests qui sont crées, un fichier destiné au javascript et au CSS relatifs à ce contrôleur.


Avant tout chose, faisons en sorte que cette action index du catalogue soit la route par défaut quand on arrive sur l'application. Pour ce faire on ouvre le fichier config/routes.rb et on définie notre route comme étant celle par défaut :

root 'catalog#index'


Le mot-clé root permet donc de définir la route par défaut. Cette route pourra être appelée dans le code via les helpers root_path et root_url.


Si on accède au site, on tombe sur la page auto-générée.


On va maintenant modifier le contrôleur pour charger nos produits puis modifier la vue pour les afficher et les mettre en valeur.

def index
  @products = Product.order(:title)
end


On récupère donc tous nos produits triés par titre. On peut maintenant passer à l'édition du template app/views/catalog/index.html.erb :

<h1>Catalogue produit</h1>

<% @products.each do |product| %>
  <div class="row mb-4">
    <div class="card w-50 bg-light">
      <div class="card-body">
        <h2 class="card-title"><%= product.title %></h2>
        <div class="row">
          <div class="col-6">
            <%= image_tag(product.image_url, width: "200") %>
          </div>
          <div class="col-6">
            <div class="card-text"><%= sanitize(product.description) %></div>
          </div>
        </div>
      </div>
      <div class="card-footer text-center font-weight-bold">
        <%= number_to_currency product.price, unit: '€', separator: ',', format: '%n %u' %>
      </div>
    </div>
  </div>
<% end %>


Le markup importe peu, si vous voulez en comprendre le détail, je vous invite à vous référer à la doc de Bootstrap. Ce qui est intéressant en revanche, c'est la boucle sur les produits, l'utilisation de sanitize et de number_to_currency.


Pour ce qui est de la boucle et de number_to_currency on a déjà vu ça dans les épisodes précédents. C'est par contre la première fois qu'on utilise sanitize. Cet helper est très pratique puisqu'il permet d'autoriser l'utilisation d'HTML en s'assurant que les tags dangereux comme script seront supprimés de la sortie final. C'est un outil précieux pour éviter les failles de type XSS.


Rechargeons notre page pour voir ce que ça donne. Et voilà qui ressemble à quelque chose. Alors non ce n'est pas le plus beau design du monde mais je vous avez prévenu, ce n'est pas mon fort. 


Ajout de tests fonctionnels


En bon développeurs que nous sommes, nous allons écrire des tests fonctionnels pour tester le comportement de notre nouvelle page.


On va donc éditer le fichier test/controllers/catalog_controller_test.rb :

test "should get index" do
    get root_url
    assert_response :success

    assert_select 'h2.card-title', Product.count
    assert_select 'h2.card-title', Product.first.title
    assert_select '.card-footer', /\d+,\d+ €/
end


Puis on joue nos tests :

$ bin/rake test:controllers


Tous nos tests passent, on est donc sûrs que notre page est bien rendu avec les éléments indispensables et qu'ils sont remplis correctement.


Gestion du cache


Cette page sera sûrement la plus fréquentée du site, c'est la page d'accueil mais également celle qui présente les produits. On peut donc raisonnablement penser qu'elle va être soumise à de fortes charges.


Pour faire en sorte que le site réponde au plus vite et alléger la charge de travail de notre serveur, nous allons mettre en place du cache de cette manière, une fois la page rendue dynamiquement une première fois, elle sera stockée dans un fichier de cache qui sera servi directement pour les requêtes suivantes. De cette manière le serveur n'a plus besoin d'aller chercher les produits en base de données puis de faire le rendu dynamique.


Par défaut, en mode développement, le cache n'est pas activé, il faut commencer par là :

$ bin/rails dev:cache


Ce qu'on veut c'est éviter de rendre à nouveau un produit s'il n'a pas changé. On ne va donc pas cacher toute la page mais chaque produit individuellement. Si on cache toute la page, la modification d'un seul produit invaliderait le cache de toute la page et le serveur devrait tout recalculer. Si par contre on cache les produits un par un, seules les portions d'HTML concernant le ou les produits qui ont changés devront être recalculés. À l'attaque :

<% @products.each do |product| %>
  <% cache product do %>
  …
  <% end %>
<% end %>


Et oui, c'est tout ce qu'il y a à faire pour générer le cache de chaque produit. La méthode cache prend un paramètre qui définie la clé la version du cache, en y passant un objet Active Record, Rails est assez intelligent pour en exploiter ses informations pour générer une clé et savoir si le cache est à jour ou non. Il est également possible de passer un tableau comme clé si votre cache dépend de plusieurs objets.


Il est également à noter qu'il est possible d'imbriquer les appels à la méthode cache. On pourrait par exemple ajouter du cache autour de l'ensemble des produits. De ce fait, à la génération de la page, plutôt que de coller des morceaux de cache les uns à la suite des autres, seul le cache parent sera utilisé lui même ayant été généré sur la base des multiples caches spécifiques aux produits. Faisons ça :

<% cache @products do %>
  <% @products.each do |product| %>
  …
  <% end %>
<% end %>


Sur des pages lourdes ou lorsque les requêtes SQL sont gourmandes, utilisé ce cache peut faire une grosse différence de performance et rendre votre application bien plus agréable à l'utilisation et moins coûteuse en terme d'hébergement.


Dans le prochain épisode nous nous attaquerons à la mise en place de la notion de panier.


À bientôt !

5/9 dans la sérieRails