Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.
Pedro Rolo
Tiago Madeira

Min Read

28 avril 2021

Requêtes sur Rails - Active Record and Arel

Cet article a été initialement publié en juillet 2018 par Pedro Rolo et mis à jour en juin 2020 par Tiago Madere .

Il existe plusieurs fonctionnalités qui font Ruby on Rails attrayant, mais là où il brille vraiment, c'est lorsqu'il s'agit d'obtenir des informations à partir de bases de données relationnelles. C'est ORM -
Actif recording - propose désormais une interface très mature, trouvant le juste équilibre entre concision et puissance.

Dans cet article, je vais fournir quelques exemples simples de la façon d'extraire des informations d'une base de données. Il ne s'agit pas d'un guide complet, mais plutôt d'un ensemble d'outils que je trouve utiles dans mon travail quotidien. De plus, ce que je présente ci-dessous est basé sur la dernière mise à jour de Rails (Rails 6).

Je vais commencer par définir un modèle de domaine par rapport auquel je vais exécuter mes requêtes :

blue arrow to the left
Imaginary Cloud logo

Our domain model

Nous utilisons le modèle de domaine suivant dans nos exemples :

Domain Model


En gros, Person et L'entreprise appartiennent à Pays, et Person et L'entreprise ont une relation plusieurs-à-plusieurs entre eux, qui est stockée dans la table des relations Persona de la entreprisa.

blue arrow to the left
Imaginary Cloud logo

Qu'est-ce qu'Active Record

Le #activerecord est ce qui lie le modèle dans notre application Ruby à sa table de base de données respective. L'objet Active record est livré avec un ensemble de méthodes qui nous aident à interroger les enregistrements de base de données. Il n'est donc pas nécessaire d'utiliser du SQL brut. À des fins de comparaison, nous présenterons la traduction de nos requêtes ActiveRecord en requêtes SQL. Vous pouvez facilement effectuer cette traduction en utilisant #to_sql.

ActiveRecord Simple Requêtes

Les requêtes les plus simples ne concernent qu'une seule table et tentent d'obtenir les enregistrements dont les colonnes comportent certaines valeurs spécifiques.

Par exemple, supposons que nous voulions savoir qui a pour prénom John :


Nous pouvons également utiliser des tableaux de valeurs souhaitables au lieu de valeurs uniques. Cela générera des requêtes utilisant le DANS Mot-clé SQL :


Outre les tableaux, les plages sont également acceptées comme prédicats de valeur :


Vous pouvez également avoir des plages infinies :


qui, avec Rails 6, peut maintenant être simplement écrit comme :


Requêtes composables ActiveRecord

Il est possible de limiter nos requêtes à plusieurs prédicats simultanés. We may be provided #where un hash avec plusieurs mots-clés ou nous pouvons enchaîner plusieurs invocations de #where:


Dans le cas contraire, nous souhaitons composer nos prédicats avec un OU nous pouvons utiliser #or.


Lorsque nous recherchons uniquement une ligne spécifique, nous pouvons utiliser #find_by à la place, qui arrête la recherche une fois qu'il trouve la première correspondance en utilisant LIMITE 1


Ou nous pouvons fournir notre propre limite personnalisée en enchaînant #limit à notre #where requêtes :

Negation Predicats

Il est possible d'obtenir les enregistrements ne correspond pas une certaine condition en utilisant #not en collaboration avec #where:


Tri

Il est possible d'utiliser #order pour trier les résultats par ordre croissant ou décroissant :


Regroupement

Plusieurs fonctions permettent de plier le résultat d'une requête en certaines valeurs, telles que #count, #maximum, #minimum et #average:


De plus, il est possible de regrouper des éléments par colonne donnée et de plier ces éléments avec ces fonctions de pliage, effectuant ainsi GROUP_PAR requêtes :


blue arrow to the left
Imaginary Cloud logo

ActiveRecord rejoint

Le cas d'utilisation le plus courant concernant plusieurs tables concerne le chargement rapide de certaines entités liées au modèle que nous avons sélectionné, qui peuvent être, par exemple, accessibles de manière itérative. Ce problème est communément appelé Problème de requêtes 1 + N et l'interaction suivante le met en évidence :


Comme nous le voyons, une nouvelle requête est effectuée chaque fois que nous demandons à une personne d'accéder à son pays.

Joint extérieur gauche avec #includes

Left Outer Join Venn Diagram

#includes nous permet de charger rapidement toutes les données en une seule fois, optimisant ainsi ce qui est effectué ci-dessus. Il se comporte comme un JOINTURE EXTÉRIEURE GAUCHE, chargeant ainsi toutes les entrées du modèle associé qui concernent nos principales entrées de modèle.


Mais attendez, ce n'est pas un JOINTURE EXTÉRIEURE GAUCHE - pourrait-on dire ! Eh bien, comme il n'y a aucune contrainte supplémentaire sur les pays que nous sélectionnons, Rails préfère recourir à un OÙ JE M'Y TROUVE requête, en tirant parti de l'index de clé primaire. Cependant, si nous ajoutons des contraintes à notre requête, Active Record exécute un JOINTURE EXTÉRIEURE GAUCHE au lieu de cela :

Ce qu'il faut remarquer dans l'exemple ci-dessus, c'est l'utilisation d'un hachage sur la condition where afin de spécifier des contraintes sur nos modèles référencés.

Nous pouvons également charger plusieurs relations à la fois :


Et il est également possible de le faire de manière imbriquée, en passant un hachage de relations à la place :


Inner rejoint #joins

Inner Join Venn Diagram

Parfois, nous ne sommes intéressés que par les enregistrements associés au module correspondant. Lorsque c'est le cas, nous utilisons #joins, qui possède la sémantique d'un JOINTURE INTÉRIEURE.

Nous illustrons la nécessité de cette fonctionnalité dans l'exemple suivant, où nous avons uniquement l'intention de faire appel à des personnes qui sont effectivement associées à un pays :


Interroger les associations ActiveRecord avec des valeurs spécifiques

Si nous ne sommes intéressés que par les enregistrements associés à un modèle associé avec des valeurs d'attributs spécifiques, nous pouvons utiliser #joins et puis #where pour spécifier les contraintes de nos modèles.

blue arrow to the left
Imaginary Cloud logo

Abstractions de requêtes réutilisables avec des méthodes de classe

Eh bien, toutes les requêtes écrites jusqu'à présent sont assez longues. Lorsqu'ils se compliquent ou sont destinés à être réutilisés via notre code, il est pratique de leur donner un nom.

Dans les anciennes versions de rails, vous devez utiliser ActiveRecord : :Base #scope méthode de classe pour créer de telles requêtes réutilisables. Vous pouvez obtenir les mêmes fonctionnalités en définissant simplement des méthodes de classe :


Après avoir défini les requêtes de cette manière, vous pouvez enchaîner ces abstractions de haut niveau.


blue arrow to the left
Imaginary Cloud logo

Qu'est-ce qu'Arel

Arel est un langage spécifique à un domaine qui permet d'exprimer vos requêtes en algèbre relationnelle. Dans les versions précédentes de Rails, il était assez courant de devoir recourir à Arel pour exécuter certaines fonctionnalités fréquemment demandées, bien qu'aujourd'hui, Active Record de Rails 6 couvre déjà la plupart de ces cas d'utilisation.

Je vais commencer par présenter certaines des requêtes Rails 6 déjà présentées en utilisant Arel au lieu d'un simple enregistrement actif. Et plus tard, concentrez-vous sur la façon d'écrire certains cas où l'on aurait encore besoin d'Arel.

Tableau Arel

Lors de la création de requêtes Arel, on commence généralement par obtenir le Arel : :Tableau objets des tables SQL avec lesquels nous voulons interagir :


Nous pouvons accéder aux colonnes de nos tables comme un hash. À partir de ces tableaux, il est possible de définir des prédicats (Arel : :Node) en invoquant des méthodes sur ses attributs, qui sont accessibles via la méthode []:

Simple request predicats Arel

Les prédicats #eq, #not_eq, #lt, #gt, #lteq, #gteq are équivalents aux opérateurs =, ! =, <, >, <=, >= et travaillez comme ceci :


Le #and & #or peut être utilisé pour créer des prédicats multitables et fonctionner de la même manière, comme ceci :


Nous pouvons ensuite transmettre ces prédicats à #where, et tant que les tables requises sont jointes, le prédicat sera converti avec succès en SQL :

Correspondances Arel (SQL LIKE)

Il s'agit d'un cas d'utilisation où il faut toujours recourir à Arel pour obtenir une requête indépendante de la base de données. Pour ce faire, il convient de combiner les #matches Prédicat Arel avec % SQL générique character :

Cela renvoie les personnes dont le nom de famille commence par le caractère « A ».

blue arrow to the left
Imaginary Cloud logo

Conclusion

Arel et Active Record proposent bien plus de fonctionnalités que celles que j'ai présentées ici. Cependant, ils sont largement suffisants pour démarrer avec des applications aux exigences simples.

En fin de compte, il s'agit de choisir de préférence entre les méthodes de requête ActiveRecord ou Arel, lorsque nous effectuons nos requêtes quotidiennes. Je trouve la syntaxe ActiveRecord plus facile à lire et à utiliser, mais Arel peut toujours être utile pour traiter des requêtes complexes.

Ready for a UX Audit? Book a free call

Vous avez trouvé cet article utile ? Ceux-là vous plairont peut-être aussi !

blue arrow to the left
Imaginary Cloud logo
blue arrow to the left
Imaginary Cloud logo
blue arrow to the left
Imaginary Cloud logo
blue arrow to the left
Imaginary Cloud logo
blue arrow to the left
Imaginary Cloud logo
Pedro Rolo
Pedro Rolo

Développeur de rails avec plus de 10 ans d'expérience dans diverses technologies. Je m'intéresse à la programmation fonctionnelle.

Read more posts by this author
Tiago Madeira
Tiago Madeira

Étudiant en informatique et à temps partiel d'ImaginaryCloud. Désireux d'apprendre de nouvelles technologies et techniques. Joueur de tennis et pianiste.

Read more posts by this author

People who read this post, also found these interesting:

arrow left
arrow to the right
Dropdown caret icon