2011-07-12 3 views
5

Je construis une API REST pour ce projet qui utilise Mongoid.Localisateur dynamique Mongoid avec Mongoid :: Errors :: DocumentNotFound exception levée

J'ai installé ce qui suit pour attraper l'exception Mongoid::Errors::DocumentNotFound:

rescue_from Mongoid::Errors::DocumentNotFound in my base controller 

Dans mon contrôleur j'ai ce code de requête:

@current_account.users.find(:first, :conditions => {:name => "some_name"}) 

La requête ci-dessus renvoie juste nil. Cela ne soulève pas l'exception. Essayé avec une autre syntaxe ainsi:

User.find(:conditions => {:name => "same"}).first 

Toutes ces méthodes fonctionne juste where interne et ne soulève where afaik pas exception, le retourne simplement []

Alors, que peut être la solution à cela? Je veux finder partiellement dynamique, mais devrait également déclencher l'exception?

Répondre

3

Je crois que Mongoid ne lèvera une exception DocumentNotFound qu'en utilisant la méthode find en transmettant l'identifiant d'un objet (et non avec des conditions). Sinon, il reviendra à zéro. De la source MongoId:

# lib/mongoid/errors/document_not_found.rb 

# Raised when querying the database for a document by a specific id which 
# does not exist. If multiple ids were passed then it will display all of 
# those. 

Vous devrez vérifier manuellement pour voir si vous avez des résultats et soit augmenter l'exception DocumentNotFound vous (pas grand), ou augmenter votre propre exception personnalisée (meilleure solution).

Un exemple de l'ancien serait quelque chose comme ceci:

raise Mongoid::Errors::DocumentNotFound.new(User, params[:name]) unless @current_account.users.first(:conditions => {:name => params[:name]}) 

Mise à jour: Je ne l'ai pas testé tout cela, mais il devrait vous permettre de faire des appels comme (ou au moins vous orienter dans la bonne direction - je l'espère):

@current_account.users.where!(:conditions => {:name => params[:name]}) 

Ce qui jetteront une coutume Mongoid::CollectionEmpty erreur, si la collection retournée à partir de la requête est vide. Notez que ce n'est pas la solution la plus efficace, car pour savoir si la collection retournée est vide, elle doit réellement traiter la requête.

Ensuite, tout ce que vous devez faire est de sauver à partir de Mongoid::CollectionEmpty (ou aussi bien).

# lib/mongoid_criterion_with_errors.rb 
module Mongoid 
    module Criterion 
    module WithErrors 
     extend ActiveSupport::Concern 

     module ClassMethods 
     def where!(*args) 
      criteria = self.where(args) 
      raise Mongoid::EmptyCollection(criteria) if criteria.empty? 
      criteria 
     end 
     end 
    end 
    end 

    class EmptyCollection < StandardError 
    def initialize(criteria) 
     @class_name = criteria.class 
     @selector = criteria.selector 
    end 

    def to_s 
     "Empty collection found for #{@class_name}, using selector: #{@selector}" 
    end 
    end 
end 

# config/application.rb 
module ApplicationName 
    class Application < Rails::Application 
    require 'mongoid_criterion_with_errors' 
    #...snip... 
    end 
end 

# app/models/user.rb 
class User 
    include Mongoid::Document 
    include Mongoid::Timestamps 
    include Mongoid::Criterion::WithErrors 
    #...snip... 
end 
+0

Eh oui, thats assez long et la répétition d'écrire à chaque fois. Je pourrais écrire une gemme pour gérer cela plus tard. Mais en raison de contraintes de temps, je vais aller de l'avant avec ce soln. Merci. – Autodidact

+0

J'ai eu un peu plus de temps sur mes mains et j'ai ajouté une solution de patch monkey rapide pour Mongoid, qui ajoute des méthodes de critères personnalisés et une erreur 'EmptyCollection' personnalisée. J'espère que cela rend les choses un peu plus gérables! :) – theTRON

+0

Eh bien, voici l'erreur: 'Failure/Error: get" # {url}/# {account.name} /non-existing.json ",: api_key => application.key méthode indéfinie expand_complex_criteria 'pour [{ : conditions => {: title => "inexistant"}}]: Array # ./lib/mongoid_criterion_with_errors.rb:8:in où! '' – Autodidact

6

J'ai rencontré le même problème aujourd'hui, et j'ai trouvé une autre solution.

Définissez raise_not_found_error à false. de sorte que votre config/mongoid.yml doit être

development: 
    host: localhost 
    port: 10045 
    username: ... 
    password: ... 
    database: ... 
    raise_not_found_error: false 

de http://mongoid.org/docs/installation/configuration.html

+0

Cela a fonctionné pour moi, merci! – HappyDeveloper