Tutorial Rubyonrails 3 - Partie 4 - ActiveRelation et scopes - Arel

Partie 4 – Rails3 -  ActiveRelation et scopes

N’hésitez à mettre des commentaires / à corriger mes fautes / à rajouter des choses !

Vous avez vu dans la partie 2 :

post = Post.where(:title => ’Mon titre’).first

Il existe de nombreux scopes ActiveRelation :

joins
limit
order
includes
where
offset

Vous aurez remarqué que ces termes ressemblent à SQL....

Donc si vous souhaitez trouver les 10 derniers commentaires visibles du post d’id 3, trié par ordre de création décroissant et qui contiennent la lettre ‘a’ dans leur contenu (l’exemple est volontairement compliqué pour que vous puissiez voir un aperçu assez complet):

comments = Comment.where(:post_id =>  3, :visible => true).where("content LIKE ?", "%a%").order(‘created_at DESC’).limit(10).all

Vous avez remarqué ce champ que j’utilise et qui apparait comme ça : created_at . Il s’agit de la date/heure de la création de l’objet. Rails l’ajoute par défaut dans la migration (ainsi que updated_at : date/heure de la dernière modification), ces champs m’ont toujours servi d’une manière ou d’une autre.
Vous noterez aussi que l'on peut chainer les scopes where.

Vous pouvez créer vos propres scopes et ils se définissent dans les models.
Par exemple si vous souhaitez filtrer les commentaires par visible :
Dans le model Comment :

class Comment < ActiveRecord::Base
 #Remarquez le singulier
 belongs_to :post
 belongs_to :reader

 scope :visible, where(:visible => true)
end

La syntaxe est :

scope :nom_du_scope, where(...).order....

Vous pouvez maintenant utiliser votre scope :

comments = Comment.where(:post_id =>  3).visible.order(‘created_at DESC’).limit(10).all

Quand vous voulez recupérer des enregistrements vous devez faire .all à la fin de l’ActiveRelation ou .first si vous ne souhaitez qu’un élément.

C’est un avantage (qui n’existait pas dans rails 2), du coup vous pouvez garder des ActiveRelations et continuer de chainer les conditions (d’un point de vue technique la requête SQL n’est executé que lorsque l’on appelle .all, .each, .length ou .first sur l’ActiveRelation):

Vous pouvez tester le chainage des scopes en console (rails c) :

ar = Comment.where(:post_id =>  3)
ar.length
ar = ar.visible
ar.length
ar = ar.order(‘created_at DESC’)
ar.length
ar = ar.limit(10)

Un peu de lecture:https://guides.rubyonrails.org/active_record_querying.html

Prochainement Partie 5 – Controller, actions