Mémo Rails


 

PARTIE 1, CONTRÔLEURS, VUE, ROUTES

1. Créer un projet Rails

mkdir projetRails
cd projetRails
rails new nomDuProjet
cd nomDuProjet

Afficher le projet en local dans un navigateur:

rails s ou rails server

2. Générateurs

Les générateur génèrent du code à trou à notre place.

Créer une page HTML(ici qq chose comme home.html)

On va générer un controller (pour rediriger le client vers la page créee) et une vue (html).

rails g controller page home

Une fois le serveur lancé, on peut se rendre à localhost:3000/page/home

On peut y lire "Find me in app/views/page/home.html.erb". Ce dossier et un fichier ont été généré. Rendons-nous y. On peut remplacer les quelques lignes HTML par ce qui nous chante, juste pour voir que ça marche. Qq chose comme <marquee>Youpie !</marquee>. Ce fichier HTML est une "vue", il n'est là que pour les beaux yeux du client.

3. Contrôleurs

Avec la commande précédente, nous avons également généré un controller dans app/controller. Dans app/controller on peut voir page_controller.rb. Le controller est executé avant le HTML. Nous avons crée avec la fameuse commande une classe PageController, héritée d'une classe de Rails, ApplicationController. Nous pouvons y voir une fonction "home" portant le même nom que notre fichier de vue.

class PageController < ApplicationController
def home
end
end

Manipuler des variables : Faire communiquer le Controlleur et la Vue

Foutons-y une variable globale (@), ici, pif, retournant "Bonjour Hercule !"

class PageController < ApplicationController
def home
@pif = "Bonjour Hercule !"
end
end

Dans la vue (home.html.erb), on peut utiliser la variable avec des balises ruby: <%= %>. Voyez plutot:

<p>
Il dit : <%= @pif%>
</p>

Et ça écrira sur le html: il dit: Bonjour Hercule !

NOTE! Le "="de <%= %> signifie "puts", ça équivaut à "echo" de php. Si on l'enlève, on pourra y faire des opérations invisbles en ruby. Un exemple:

class PageController < ApplicationController
def home
@pif = "Bonjour Hercule !"
@nombre = 10
end
end

--

<p>
Il dit : <%= @pif%>
<%resultat = @nombre * @nombre #resultat et une variable locale, on y calcule le carré de @nombre %>
<p><%= resultat %></p>
</p>

Et ça écrit 100. On pourra entre autres y placer des boucles et des conditions également…

4. Routes, Controleurs

On va voir ici comment créer d'autres pages, et modifier les URL (routes).

Dans config/routes.rb, on peut voir à l'interieur de "Rails.application.routes.draw do:

get 'page/home'

Plaçons cette ligne en commentaire et mettons cela:

get 'nimportequoi' => 'page#home'

Si on va sur localhost:3000/nimportequoi, on peut acceder à notre fameuse vue home.

« page#home » signifie que la route castor doit aller chercher, dans le contrôleur PageController, la fonction home.

Décommentons la ligne, et on peut voir que les deux URL fonctionnent, en /nimportequoi et en page/home.

Résumons. Pour faire une nouvelle page issu de "Page", il faudra créer un nouveau fichier HTML (côté vue) en .html.erb. Ensuite, une nouvelle fonction à l'interieur du Controlleur "Page" (ex: def contact end) et une route, pour pouvoir y acceder via des URL plus sympathiques.

Associer l'index (localhost:3000) à une vue.

Ajouter par exemple:

root 'page#home'

5. Layout: Acceder aux balises HTML structurantes (on va dire importantes)

Observons le fichier app/views/layouts/application.html.erb.

Le contenu de nos vues viendra s’immiscer à la place de « <%= yield %> ». Si nous retirons cette ligne, nos pages ne s’afficheront plus !


 PARTIE DEUX, BASE DE DONNEES

1. Création d'une Table (en exemple nous voulons enregistrer des articles)

Une table est un premier ensemble de données. Exemple: Une table Article (contenants les articles) elle pourrait contenir au moins 4 colonnes:

IDentifiant Titre Contenu Auteur
1 "Mon premier post" "Ceci est mon premier post…" NiouDélit
2 "Recette Mirabelles" "Alors tout d'abord, prenez…" Papagenau

(1 ligne = 1 entrée)

Il y a quelques règles typographiques inhérantes à la gestion des données :

Voici ce qu'il faut taper premièrement dans le terminal pour créer une table:

rails generate migration TableArticles

Ce qui génère dans le dossier db/migrate un fichier nommé pleindechiffres_table_articles.rb. Ce fichier est une migration.

class TableArticles < ActiveRecord::Migration
def change
end
end

Ce fichier permet de changer la structure de votre base de données. Changer la structure d’une base de données, c’est ajouter, supprimer ou modifier une table ou une colonne. C’est comme remplir la première ligne d’un tableur avec le nom des colonnes. Si ces noms changent, il faut faire une migration pour changer sa structure.
I
l n’y a pas besoin de migration si l’on ajoute ou supprime une entrée.

On va ajouter

class TableArticles < ActiveRecord::Migration
def change
create_table :articles
add_column :articles, :titre, :string
end
end

Deux étapes :

  1. Nous utilisons la fonction create_table, qui prend pour argument le nom de la table à créer ;

  2. Nous ajoutons une colonne avec la fonction add_column, qui prend trois arguments : le nom de la table sur laquelle ajouter la colonne, le nom de la colonne et son type.

Maintenant que nous avons créé une table, il faut qu'elle soit prise en compte:

rake db:migrate
La commande rake est une boite à outils. Elle permet de faire plein de choses, notamment d’exécuter les migrations pour qu’elles soient prises en compte. Une migration ne s’exécute qu’une seule fois. Si vous faites une 2e fois cette commande, il ne se passera rien. Ce qui veut dire que si vous avez oublié quelque chose dans votre migration, il vous faudra en générer une autre, dans un nouveau fichier ! Et dans cette autre migration, vous n’aurez pas besoin de répéter ce qui vous avez déjà fait, n’y mettez que ce qu’il vous manque.

Maintenant, il faut lier la BDD qui contient une table avec Rails. Pour cela, on va créer un fichier dans le dossier models, ici, "article.rb", voici son contenu

class Article < ActiveRecord::Base
end

On appelera ce fichier "modele" ou classe, il représente une table d'une base de donnée. Par convention, le nom de la classe-modèle sera le même que le nom de la table… Mais au singulier!

Pour vérifier si tout fonctionne ou si rien n'a été oublié, il faut acceder à la console rails avec:

rails console
ou rails c

En tapant le nom de la classe représentant la BDD on peut voir si ça n'affiche point d'erreurs. En cas d'erreur, il faudra sans doute installer les gems manquantes ou faire les mises à jours. Pour sortir de la console, il faut utiliser la commande exit.

ça y est notre BDD est opérationnelle ! On va ajouter des entrées (ou lignes) dans notre BDD pour inserer du contenu à notre blog.

2. Ajouter, modifier, supprimer des entrées à la BDD

- En passant par la console

• Par le biais de la console Rails, c'est très simple d'ajouter des articles (entrées ou lignes).

mon_premier_article = Article.new #création d'une instance de classe
mon_premier_article.titre = "Bienvenu" #Cette article est titré "Bienvenu"
mon_premier_article.save #et on envoie ça à la bdd qu'elle puisse en prendre compte

on peut aussi faire plus court:

Article.create titre: "Mirabelles à gogo"

Par défaut, chaque nouvel objet est identitfié avec un clé id. Notre premier article à pour id "1". Le deuxième aura 2, etc.

Pour afficher toutes les entrées (ou les objets) on tapera :

Article.all

• Pour modifier une ligne, on peut rechercher une entrée via son id:

mon_premier_article = Article.find(1)
mon_premier_livre.title = "Bonjour"
mon_premier_livre.save #on oublie pas de sauvegarder ;-)

Pour supprimer une ligne, il faudra aussi retrouver l'objet via son idée et utiliser une petite fonction, et on peut condenser un peu le tout de cette façon:

Article.find(1).destroy

- Afficher sur mon site des données de la BDD…

Et sans passer par la console rails? CAD en passant par une interface web? Hé oui jusqu'à preuve du contraire, sur un blog, pour poster qqchose, on passe par une interface, pas par une console austère de programmeurs. Dans ce cas on va créer une nouvelle page de gestion du bazar. Ça sous-entend qu'on va créer une nouvelle vue qui affichera tous nos articles. Mais qui dit nouvelle vue, dit controlleur pour générer le code adéquat. Mais qui dit nouveau controleur dit aussi nouveaux routeurs !

On va créer un index de nos articles créés:

rails generate controller articles index

On peut maintenant se rendre sur la page localhost:3000/articles/index, mais rien d'intéressant.
Dans la classe ArticlesController, on va un peu modifier la fonction index.

Ajoutons-y une variable globale qui récupérera toutes les entrées de notre classe Article contenant toutes les lignes de la BDD.

def index
@test = Article.all
end

Notre variable test est en fait un tableau d'objets (du coup). Pour afficher l'ensemble des entrées maintenant contenues dans notre variable test globale, on le parcourera avec une boucle, dans la vue:

<% @test.each do |article| %>
<p><%= article.titre %></p>
<% end %>

Rappel: Nos lignes ne comprennent qu'une colonne titre, execpté leurs id.

On pourra, par pure coquetterie changer la route du bazar. Dans le dossier config, dans routes.rb on pourra ajouter:

get 'lesArticles' => 'articles#index'

Et voilà. Allez un rappel du fonctionnement de Rails. On rabache mais y a que ça de vrai:

  1. Un utilisateur demande l’affichage d’une page du site ;

  2. Le fichier des routes appelle la bonne fonction du bon contrôleur ;

  3. Si besoin, le contrôleur récupère, modifie ou supprime des données via le modèle ;

  4. Le modèle répercute ces modifications dans la base de données ;

  5. Le contrôleur appelle la vue, qui construit la page HTML ;

  6. Une fois la page HTML construite, celle-ci est envoyée au navigateur de l’utilisateur.

• Formulaire: Interagir avec la base directement depuis la vue

1. Ajouter un article via un formulaire

Pour créer un formulaire qui permet d'ajouter des lignes à la BDD, nous allons utiliser des fonctions assez spécifiques qui retournent du HTML: des helpers.

<%= form_tag "/lesArticles", method: "post" do %>
<input type="text" name="titre">
<input type="submit" value="Créer article"
<% end %>

Et si on actualise notre page, on a bel et bien un formulaire qui s'affiche avec un joli bouton "Créer un article". Mais jusqu'ici, ce n'est rien que du HTML inoffensif. On notera qu'on utilise la méthode "post" pour envoyer des données (get lui est relatif aux URL)

Notre formulaire envoie sur la page lesArticles avec la méthode post.

Si on regarde notre fichier de route root.rb . La fonction

get 'lesArticles' => 'articles#index'

renvoie sur le controller articles utilisant la fonction index

get donnée saisie par l utilisateur (url) ou clique lien
post, données issu d'un formulaire

On va créer une nouvelle route, pas en get, mais en post, qui renvera au controlleur articles mais avec une fonction autre fonction, ici create, qu'on va creer.

post 'lesArticles' => 'articles#create'

Du coup, on va dans le fichier contrler d'articles et on ajoute la fonction create (def create end)

Voilà : quand nous cliquons sur le bouton « Ajouter le livre », c’est le code de la fonction create de ArticlesController qui sera exécuté.

Que mettre dans la fonction create ? Si vous avez bien suivi, vous vous doutez qu’il y aura, au choix, un Article.new ou un Article.create. Mais il vous manque une information : comment récupérer ce que l’utilisateur a saisi dans le formulaire ?

La réponse est la suivante : la variable params. C’est une variable de type Hash dont les clés coïncident avec les attributs name du formulaire, et les valeurs sont les saisies de l’utilisateur. Par exemple : params[:title].

def create
Article.create titre: params[:titre]
end

Une fois qu'on clique sur bouton envoyer, il faut dire au navigateur quelle page HTML envoyée. On n'a pas de HTML (ou vue) associé à la fonction create.

Est-ce qu’il faut créer une nouvelle vue pour cette fonction ? A priori, oui… mais cette vue serait exactement la même que l’index. Il ne serait pas très élégant de dupliquer le code de la vue. Je vous présente une astuce : la redirection. Une redirection permet de rediriger le navigateur vers une autre route. Par exemple :

def create
Article.create titre: params[:titre]
redirect_to "lesArticles"
end

les redirect_to sont en get, on renvoie sur la route "lesArticles", qui nous renvoie sur la fonction index, ce qui revient à rester sur la même page.

2. Afficher les articles séparément, seul.

Bien, imaginons que le titre de nos articles soient aussi des liens qui mènent à l'affichage de l'article seul. Tout d'abord reflechissons au lien: localhost:3000/lesArticles affiche tous les articles car la route lesArticles est issue du controller Articles qui renvoie utilise la fonction index (qui affiche tous les articles avec Article.all)

Le lien d'un article seul pourrait avoir un lien avec son id:

localhost:3000/lesArticles/2

On passe par de l'url, ça sent le get à plein nez. Bien, allons sur la vue d'articles pour placer des liens sur les titres.

Initialement nous avons ça, qui affiche tous les titres:

<% @test.each do |article| %>
<p><%= article.titre %></p>
<% end %>

Si nous voulons créer une URL du genre localhost:3000/lesArticles/2, il faudra faire ainsi :

<h1>Articles écrits :</h1>
<% @test.each do |article| %>
<p><a href="/lesArticles/<%= article.id %>"><%= article.titre %></a></p>
<% end %>

ça ne va pas marcher, allons sur la route pour pouvoir effectuer un petit tour en passant par la case controlleur/fonction. Dans routes.rb ajoutons:

get 'lesArticles/:id' => 'articles#show'

ça veut dire que si on accède à l'URL ../lesArticles/3 (par exemple) on sera renvoyé vers le controlleur qui effectura la fonction show (qu'on va créer)

Allons sur le controlleur d'article et créeons une fonction show (par convention). Comme nous voulons montrer un seul article, on va effectuer une recherche avec la fonction .find (qu'on a déjà utilisé dans la console rails). Pour récupérer la saisie en get de l'utilisateur, nous allons devoir utiliser encore la hash params.

La fonction s'écrit de cette façon:

def show
@l_article = Article.find(params[:id])
end

Nous mettons le résultat dans une variable globale pour qu'on puissen en récupérer le contenu dans la vue (qui affichera l'article). Vue qu'on va créer dans le dossier articles. on va l'appeller show.html.erb

<h1>L'article</h1>
<%= @l_article.titre %>

On applique la fonction titre pour y afficher la proprité relative, et ça marche normalement.

Modifier un article via un formulaire

On va foutre le formulaire dans la page de l'article à modifier. On va utiliser un helper comme on a vu avant, sauf qu'on va utiliser la méthode patch, plutot que la méthode post (pour modifier c'comme ça)

<%= form_tag "/lesArticles/#{@l_article.id}", method: "patch" do %>
<input type="text" name="titre"/>
<input type="submit" value="Modifier"/>
<% end %>

On va faire une petite route, hom sur route.rb. On va écrire:

patch "lesArticles/:id" => "articles#update"

On oublie pas de préciser l'id car l'action se porte sur un seul article. On route la bazar vers une fonction update (convention!). Il nous faut donc créer la fonction update dans le controlleur et une vue.

def update
@l_article = Article.find(params[:id])
@l_article.titre = params[:titre]
@l_article.save
redirect_to "/lesArticles/#{params[:id]}"
end

On trouve l'article à modifier avec .find, on modifie le contenu du titre à changer avec l'entrée utilisateur (avec params, toujours) et on sauvegarde avec .save. On redirige vers la page de l'article, qui récupére toujours l'id de l'article qui a été modifié avec params, à l'interieur d'une chaine de caractère (avec #{}).

Et la ça marche normalement.

Supprimer des données

Comme d'hab, on va ajouter le formulaire (toujours avec un helper), enfin, ici le bouton de suppression de l'article dans la vue, dans le show de l'article.

<%= form_tag "lesArticles/#{@l_article.id}", method: "delete" do %>
<input type="button" value="Supprimer cette merde"/>
<% end %>