Quand j'ai un tableau d'identifiants, comme
ids = [2,3,5]
et je joue
Comment.find(ids)
tout fonctionne bien. Mais quand il y a un identifiant qui n'existe pas, j'obtiens une exception. Cela se produit généralement lorsque je reçois une liste d’ID correspondant à certains filtres et que je fais quelque chose comme:
current_user.comments.find(ids)
Cette fois, je peux avoir un ID de commentaire valide, qui n'appartient cependant pas à un utilisateur donné. Il n'est donc pas trouvé et une exception me parvient.
J'ai essayé find(:all, ids)
, mais il renvoie tous les enregistrements.
Le seul moyen de le faire maintenant est
current_user.comments.select { |c| ids.include?(c.id) }
Mais cela me semble une solution super inefficace.
Existe-t-il un meilleur moyen de sélectionner ID dans Array sans obtenir d'exception pour un enregistrement non existant?
S'il s'agit simplement d'éviter les exceptions qui vous inquiètent, la famille de fonctions "find_all_by .." fonctionne sans exception.
Comment.find_all_by_id([2, 3, 5])
fonctionnera même si certains identifiants n'existent pas. Cela fonctionne dans le
user.comments.find_all_by_id(potentially_nonexistent_ids)
cas aussi.
Comment.where(id: [2, 3, 5])
Mise à jour: Cette réponse est plus pertinente pour Rails 4.x
Faire ceci:
current_user.comments.where(:id=>[123,"456","Michael Jackson"])
Le point fort de cette approche est qu’elle renvoie un objet Relation
, auquel vous pouvez joindre davantage de clauses .where
, De clauses .limit
, Etc., ce qui est très utile. Il permet également des identifiants inexistants sans générer d'exceptions.
La nouvelle syntaxe Ruby serait la suivante:
current_user.comments.where(id: [123, "456", "Michael Jackson"])
Si vous avez besoin de plus de contrôle (vous devez peut-être indiquer le nom de la table), vous pouvez également procéder comme suit:
Model.joins(:another_model_table_name)
.where('another_model_table_name.id IN (?)', your_id_array)
Maintenant, les méthodes .find et .find_by_id sont obsolètes dans Rails 4. Nous pouvons donc utiliser ci-dessous:
Comment.where(id: [2, 3, 5])
Cela fonctionnera même si certains identifiants n'existent pas. Cela fonctionne dans le
user.comments.where(id: avoided_ids_array)
Aussi pour exclure les ID
Comment.where.not(id: [2, 3, 5])
Pour éviter que des exceptions ne tue votre application, vous devez intercepter ces exceptions et les traiter comme vous le souhaitez, en définissant le comportement de votre application dans les situations où l'identifiant n'est pas trouvé.
begin
current_user.comments.find(ids)
rescue
#do something in case of exception found
end
Voici plus d'infos sur les exceptions en Ruby.
Vous pouvez aussi l'utiliser dans named_scope si vous voulez y mettre d'autres conditions
par exemple inclure un autre modèle:
named_scope 'get_by_ids', lambda {| ids | {: include => [: commentaires],: conditions => ["comments.id IN (?)", ids]}}