J'utilise Rails 2.3.5 et en ce que si je donne Model.find(1)
et si 1 n'est pas dans la base de données, l'erreur ActiveRecord est renvoyée. Devrait-il simplement renvoyer nil
comme dans le cas de Model.find_by_column('..')
?
C'est le comportement attendu. Je pense que David explique le mieux lui-même, voici donc une citation de Ruby, S., Thomas, D. et Hansson, DH, 2009. Développement Web agile avec Rails , troisième édition, troisième édition Edition., Bibliothèque pragmatique (p.330).
Lorsque vous utilisez un Finder piloté par Clés primaires, vous recherchez un enregistrement Particulier. Vous vous attendez à ce que Existe. Un appel à Person.find (5) est Basé sur notre connaissance de la table des personnes . Nous voulons une ligne avec un identifiant de 5. Si cet appel échoue (si l'enregistrement avec l'identifiant de 5 a été détruit), nous nous trouvons dans une situation exceptionnelle . . Ceci impose la levée D'une exception et Rails soulève donc RecordNotFound.
D'autre part, Personnes qui utilisent des critères pour rechercher Recherchent une correspondance. Donc, Person.find (: first, : Conditions => "name = 'Dave'") est l’équivalent De dire à la base de données (comme une boîte noire) «Donnez-moi la première personne qui porte le nom de Dave.» Ce présente une approche distinctement différente en matière de récupération; nous ne sommes pas certains d’avance que nous obtiendrons un résultat. Il est tout à fait possible que le jeu de résultats soit vide. Ainsi, si l'on retourne zéro dans Le cas des détecteurs qui recherchent Une rangée et un tableau vide pour les trouveurs Qui recherchent plusieurs rangées est le Naturel, non exceptionnel réponse.
Si vous ne voulez vraiment pas l'exception, vous pouvez utiliser find_by_id
:
# @user = User.find(params[:id]) # original code
@user = User.find_by_id(params[:id])
if @user
# found!
else
# not found
end
Cela devrait être plus rapide qu'un contrôle exists?
séparé.
EDIT: Notez que comme @Miguelgraz a commenté, dans Rails 4, vous devriez plutôt dire User.find_by(id: params[:id])
. Même fonctionnalité, mais maintenant, l'implémentation n'aura plus besoin de method_missing
.
lancer l'exception est le comportement attendu.
en fait, dans le cours normal des événements, si vous laissez l'exception rester indemne, votre serveur Rails renverra la bonne page 404 non trouvée.
si vous souhaitez que le résultat soit nul, vous pouvez le prendre vous-même:
begin
@model = Model.find(id_provided)
rescue ActiveRecord::RecordNotFound => e
@model = nil
end
Si vous souhaitez que l'exception soit générée dans les variantes de find_by_attributes des méthodes Finder, vous pouvez utiliser le bang! version de la méthode.
Par exemple,
Model.find_by_category!(a_category_value)
recordNotFound sera lancé si aucune correspondance n'est trouvée.
J'ai trouvé cela DRY dans des scénarios tels que les contrôleurs RESTful, où j'ai un gestionnaire d'erreurs commun pour l'exception et je veux que mes actions se comportent de manière cohérente lorsqu'une ressource correspondant aux paramètres donnés est introuvable.
Méthode Rails 4
if user = User.find_by(id: params[:id])
#do something with user
else
#throw error or redirect
raise ActiveRecord::RecordNotFound
end
Vous pouvez vérifier si l'enregistrement existe avant de le récupérer.
@model = Model.find(id) if Model.exists?(id)
Vous pouvez utiliser find_by avec l'attribut requis (dans votre cas, l'id). Cela retournera nil au lieu de donner une erreur si l'id donné n'est pas trouvé.
Model.find_by_id(id_value)
Vous pouvez également utiliser où mais vous devez savoir que pour renvoyer une relation d’enregistrement actif avec zéro enregistrement ou plus, vous devez d’abord utiliser pour renvoyer un seul enregistrement ou nil si aucun enregistrement n’est renvoyé.
Model.where(id: id_value).first