【问题标题】:Mongoid dynamic finder with Mongoid::Errors::DocumentNotFound exception raised引发 Mongoid::Errors::DocumentNotFound 异常的 Mongoid 动态查找器
【发布时间】:2011-07-12 09:11:53
【问题描述】:

我正在为这个使用 Mongoid 的项目构建一个 REST api。

我已设置以下内容来捕获Mongoid::Errors::DocumentNotFound 异常:

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

在我的控制器中,我有这个查询代码:

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

上面的查询只返回nil。它不会引发异常。 也尝试了另一种语法:

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

所有这些方法都只是在内部运行 where 而 afaik where 不会引发异常,它只是返回 []

那么有什么办法可以解决这个问题呢?我想要部分动态查找器,但也应该引发异常?

【问题讨论】:

    标签: ruby-on-rails-3 mongoid


    【解决方案1】:

    我今天遇到了同样的问题,找到了另一个解决方案。

    raise_not_found_error 设置为false。所以你的 config/mongoid.yml 应该是

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

    来自http://mongoid.org/docs/installation/configuration.html

    【讨论】:

      【解决方案2】:

      我相信 Mongoid 只会在使用 find 方法时通过传入对象的 id(而不是条件)引发 DocumentNotFound 异常。否则它将返回零。来自 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.
      

      您必须手动检查是否有任何结果,然后自己引发 DocumentNotFound 异常(不是很好),或者引发您自己的自定义异常(更好的解决方案)。

      前者的一个例子是这样的:

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

      更新:我还没有测试过这些,但它应该允许你拨打电话(或至少为你指明正确的方向 - 我希望!):

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

      如果从查询返回的集合为空,则会引发自定义 Mongoid::CollectionEmpty 错误。请注意,这不是最有效的解决方案,因为为了确定返回的集合是否为空 - 它必须实际处理查询。

      那么你需要做的就是从Mongoid::CollectionEmpty 中解救出来(或者也一样)。

      # 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
      

      【讨论】:

      • 是的,每次都写很长而且重复。以后我可能会写一个 gem 来处理这个问题。但是由于时间限制,我将继续进行此解决方案。谢谢。
      • 我有更多的时间,我为 Mongoid 添加了一个快速的猴子补丁解决方案,它添加了自定义标准方法和自定义 EmptyCollection 错误。希望这能让事情变得更易于管理! :)
      • 这是错误:Failure/Error: get "#{url}/#{account.name}/non-existing.json", :api_key =&gt; application.key undefined method expand_complex_criteria' for [{:conditions=&gt;{:title=&gt;"non-existing"}}]:Array # ./lib/mongoid_criterion_with_errors.rb:8:in where!'
      • *args splat 更改为opts={} 修复了它。非常感谢。
      猜你喜欢
      • 2013-09-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多