具有Mongoid :: Errors :: DocumentNotFound异常的Mongoid动态查找程序引发

Aut*_*act 5 mongoid ruby-on-rails-3

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

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

rescue_from Mongoid::Errors::DocumentNotFound in my base controller
Run Code Online (Sandbox Code Playgroud)

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

@current_account.users.find(:first, :conditions => {:name => "some_name"})
Run Code Online (Sandbox Code Playgroud)

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

User.find(:conditions => {:name => "same"}).first
Run Code Online (Sandbox Code Playgroud)

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

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

小智 6

我今天遇到了同样的问题,并找到了另一种解决方案.

设置raise_not_found_errorfalse.所以你的config/mongoid.yml应该是

development:
  host: localhost
  port: 10045
  username: ...
  password: ...
  database: ...
  raise_not_found_error: false
Run Code Online (Sandbox Code Playgroud)

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


the*_*RON 3

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

您必须手动检查是否获得任何结果,并自行引发 DocumentNotFound 异常(不太好),或引发您自己的自定义异常(更好的解决方案)。

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

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

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

@current_account.users.where!(:conditions => {:name => params[:name]})
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)