Je suis un développeur PHP qui apprend la gaieté de Ruby on Rails, j’aime ActiveRecord et j’ai remarqué quelque chose de très intéressant. Les méthodes ActiveRecord détectent la chaîne de fin de méthode pour exécuter la requête.
@person = Person.where(name: 'Jason').where(age: 26) # In my humble imagination I'd think that each where() executes a database query # But in reality, it doesn't until the last method in the chain
Comment fonctionne cette sorcellerie?
La méthode where
renvoie un object ActiveRecord::Relation
et, par lui-même, cet object n’émet pas de requête de firebase database. C’est là que vous utilisez cet object qui compte.
Dans la console, vous faites probablement ceci:
@person = Person.where(name: "Jason")
Et puis, blammo émet une requête de firebase database et renvoie ce qui semble être un tableau de tout le monde nommé Jason. Yay, Active Record!
Mais alors vous faites quelque chose comme ça:
@person = Person.where(name: "Jason").where(age: 26)
Et puis cela émet une autre requête, mais celle-ci concerne les personnes qui s’appellent Jason qui ont 26 ans. Mais il ne s’agit que d’ une seule requête, alors où est passée l’autre requête?
Comme d’autres l’ont suggéré, cela se produit car la méthode where
renvoie un object proxy. En réalité, il n’effectue pas de requête et ne renvoie pas de jeu de données, sauf si cela lui est demandé.
Lorsque vous exécutez quoi que ce soit dans la console, la version inspectée du résultat de votre exécution est affichée. Si vous mettez 1
dans la console et appuyez sur Entrée, vous obtiendrez 1
retour parce que 1.inspect
est 1
. La magie! Même chose pour "1"
. Une variété d’autres objects n’a pas de méthode d’ inspect
définie et Ruby se rabat sur celle de Object
qui renvoie quelque chose de terrible comme .
Chaque object ActiveRecord::Relation
possède la méthode inspect qui lui est associée afin de provoquer une requête. Lorsque vous écrivez la requête dans votre console, IRB appelle inspect
sur la valeur de retour de cette requête et affiche quelque chose de presque lisible, comme le tableau que vous voyez.
Si vous émettiez cela dans un script Ruby standard, aucune requête ne serait exécutée tant que l’object n’aurait pas été inspecté (par inspect
) ou itéré en utilisant each
, ou si la méthode to_a
appelée.
Jusqu’à ce que l’une de ces trois choses se produise, vous pouvez enchaîner autant d’instructions where
vous voulez et ensuite, lorsque vous appelez to_a
, to_a
ou each
d’elles, elle exécutera finalement cette requête.
Il existe un certain nombre de méthodes appelées “kickers” qui déclenchent la requête dans la firebase database. Auparavant, ils créaient simplement des nœuds AST qui, une fois lancés, génèreraient le SQL réel (ou le langage en cours de compilation) et exécuteraient la requête.
Voir ce billet de blog pour une explication plus approfondie de la façon dont cela est fait.
Vous pouvez lire le code, mais un concept ici est le modèle de proxy.
Probablement @personnel n’est pas l’object réel mais un proxy pour cet object et lorsque vous avez besoin d’un atsortingbut, l’enregistrement actif exécute finalement la requête. Hibernate a le même concept.
Peut-être un peu trop tard mais vous pouvez utiliser un hachage:
@person = Person.where({name: "Jason", age: 26})
Requête résultante:
SELECT "person".* FROM "person" WHERE "person"."name" = 'Jason' AND "person"."age" = 26