我有一个通过Mongoid连接到MongoDB的Sinatra应用程序。它工作正常,直到我开始得到一个奇怪的错误,我无法在stackoverflow或任何地方找到任何地方。
请注意,在Heroku上部署了相同的代码,它与相同的数据库版本Mongo 3.0.7,我在本地以及2.2.3尝试的ruby版本2.0.0一起正常工作。当我通过网络运行霰弹枪和运行Rspec时出现错误:
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'
我的Rspec代码:
RSpec.describe Bible::Book do
describe "#get_book_id" do
it "finds the id of genesis" do
expect(Bible::Book.get_book_id 'genesis').to eq 1
end
end
end
代码实现是:
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
My 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上工作正常,但不是我的机器:(
答案 0 :(得分:0)
我不确定这是否是您问题的根源,但我在您的get_book_id
类方法中看到了一些奇怪的事情。
首先,这永远不会离开book.nil?
:
book = where(:title => book_title.downcase.strip)
这会在[{1}}中留下Mongoid::Contextual
,查询可能会或可能找不到任何内容,但book
在任何一种情况下都不会book
。这意味着你的:
nil
下一行没有做任何有用的事情。这也意味着return unless book
可以book[0]
在这里:
nil
当您通常拨打book[0]._id
时,您也会调用_id
方法。
我认为你的方法会更好:
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).first
如果无法找到,book = find_by(...)
会nil
book
<{1}}中的任何内容和Bible::Book
,如果能够找到某些内容的话。
如果您有ActiveSupport,您也可以说:
book
隐藏find_by(:title => book_title.downcase.strip).try(:id)
支票。您也可以通过nil
调用只将only
拉出MongoDB:
_id
答案 1 :(得分:0)
当为mongoid:uri: <%= ENV['MONGOLAB_URI'] %>