Ruby Mongoid::context#每个委托给context.each,但context为零
我有一个Sinatra应用程序通过Mongoid连接到MongoDB。它工作得很好,直到我开始出现一个奇怪的错误,我在stackoverflow或任何地方都找不到 请注意,在Heroku上部署了相同的代码,并且在相同的数据库版本Mongo3.0.7、ruby版本2.0.0(我在本地尝试过)和2.2.3下也可以正常工作。我在web上运行shotgun和运行Rspec时出错:Ruby Mongoid::context#每个委托给context.each,但context为零,ruby,mongodb,sinatra,mongoid,Ruby,Mongodb,Sinatra,Mongoid,我有一个Sinatra应用程序通过Mongoid连接到MongoDB。它工作得很好,直到我开始出现一个奇怪的错误,我在stackoverflow或任何地方都找不到 请注意,在Heroku上部署了相同的代码,并且在相同的数据库版本Mongo3.0.7、ruby版本2.0.0(我在本地尝试过)和2.2.3下也可以正常工作。我在web上运行shotgun和运行Rspec时出错: Bible::Book#get_book_id is case-insensitive Failure/Error: bo
Bible::Book#get_book_id is case-insensitive
Failure/Error: book[0]._id
Module::DelegationError:
Mongoid::Contextual#each delegated to context.each, but context is nil: #<Mongoid::Criteria
selector: {"title"=>"genesis"}
options: {}
class: Bible::Book
embedded: false>
# /Users/issa/.rvm/gems/ruby-2.2.3/gems/mongoid-5.0.0/lib/mongoid/contextual.rb:20:in `rescue in each'
# /Users/issa/.rvm/gems/ruby-2.2.3/gems/mongoid-5.0.0/lib/mongoid/contextual.rb:20:in `each'
# /Users/issa/.rvm/gems/ruby-2.2.3/gems/mongoid-5.0.0/lib/mongoid/criteria.rb:554:in `entries'
# /Users/issa/.rvm/gems/ruby-2.2.3/gems/mongoid-5.0.0/lib/mongoid/criteria.rb:554:in `method_missing'
# ./app/bible/book.rb:52:in `get_book_id'
# ./spec/bible/book_spec.rb:11:in `block (3 levels) in <top (required)>'
# ------------------
# --- Caused by: ---
# NoMethodError:
# undefined method `each' for nil:NilClass
# /Users/issa/.rvm/gems/ruby-2.2.3/gems/mongo-2.1.2/lib/mongo/cluster.rb:114:in `initialize'
代码实现如下所示:
module Bible
class Book
include Mongoid::Document
store_in collection: "bible_books"
field :title, type: String
field :testament, type: String
...
def self.get_book_id book_title
book = where(:title => book_title.downcase.strip)
return unless book
book[0]._id
end
end
end
我的Gemfile中包含MongoDB的以下部分:
# MongoDB
...
gem 'mongoid', '~> 5.0'
gem 'bson_ext'
gem 'bson'
真奇怪,我只在我的机器上出现了这个错误,而且是突然开始的。我正在使用OS X El Capitan。我可以从命令行访问mongodb集合而不会出现问题,并且可以运行相同的等效查询以获得我想要的结果:
> use bible
switched to db bible
> db.bible_books.find({"title": "genesis"})
{ "_id" : 1, "title" : "genesis", "testament" : "old", "chapters" : 50, "doc_type" : "book", "canon_type" : "canonical", "canon_order" : 1, "full_name" : { "en" : "The book of Genesis", "ar" : "سفر التكوين" }, "short_name" : { "en" : "Genesis", "ar" : "التكوين" }, "abbr_name" : { "ar" : "تك", "en" : "Gen" } }
我尝试了其他集合、其他查询、其他变体,但仍然得到相同的错误。我还原到github中的一个旧代码,该代码确实有效,但仍然存在相同的问题,因此我很清楚,我的代码或配置中没有任何错误。我尝试了2.0.0-2.2.3的不同ruby版本,4-5的不同mongoid版本。。。同样,相同版本的代码和安装在Heroku上也可以正常工作,但在我的机器上不行:(我不确定这是否是问题的根源,但我在您的
get\u book\u id
类方法中看到了一些奇怪的事情
首先,这永远不会离开book.nil?
:
book = where(:title => book_title.downcase.strip)
这将给您留下一个Mongoid::context
,在book
中,查询可能会或可能不会找到任何内容,但book
在任何情况下都不会是nil
。这意味着您的:
return unless book
在下一行中没有任何有用的内容。这也意味着book[0]
在这里可以是nil
:
book[0]._id
当您通常调用id
时,您也在调用\u id
方法
我认为你的方法最好是这样:
def self.get_book_id book_title
book = find_by(:title => book_title.downcase.strip)
return unless book
book.id
end
find_by(query)
只是说where(query)的一种简短方式。首先sobook=find_by(…)
如果你在book
中找不到任何东西,你会在book
中找到一本Bible::book
,如果你能找到什么
如果您有可用的ActiveSupport,您还可以说:
find_by(:title => book_title.downcase.strip).try(:id)
要隐藏nil
检查,还可以抛出only
调用,仅从MongoDB中拉出\u id
:
book = only(:id).find_by(:title => book_title.downcase.strip)
return unless book
book.id
# or, if ActiveSupport is around, just this:
only(:id).find_by(:title => book_title.downcase.strip).try(:id)
当为mongoid指定了错误的生产配置url时,我遇到了类似的错误:uri:
当我没有正确设置环境变量时,我遇到了类似的错误。这是一条很难理解的错误消息。
book = only(:id).find_by(:title => book_title.downcase.strip)
return unless book
book.id
# or, if ActiveSupport is around, just this:
only(:id).find_by(:title => book_title.downcase.strip).try(:id)