Mongoid Model.find在规范中失败,但在app中工作

时间:2014-04-05 05:40:05

标签: ruby-on-rails ruby rspec mongoid bson

下一行:

  User.find(session[:user_id])

其中session[:user_id]之前已定义:

  session[:user_id] = user.id

在规范中工作正常并返回用户模型,但在实际应用程序(开发模式)中它失败:

MOPED: 127.0.0.1:27017 QUERY        database=rails_api_development collection=users selector={"_id"=>{"$oid"=>BSON::ObjectId('533c3958616c641142010000')}} flags=[] limit=0 skip=0 batch_size=nil fields=nil runtime: 1.0680ms
Completed 500 Internal Server Error in 15ms

Moped::Errors::QueryFailure - The operation: #<Moped::Protocol::Query
    @length=89
@request_id=2
@response_to=0
@op_code=2004
@flags=[]
@full_collection_name="rails_api_development.users"
@skip=0
@limit=0
@selector={"_id"=>{"$oid"=>BSON::ObjectId('533c3958616c641142010000')}}
@fields=nil>
    failed with error 10068: "invalid operator: $oid"

See https://github.com/mongodb/mongo/blob/master/docs/errors.md
for details about this error.:
  moped (2.0.0.rc1) lib/moped/operation/read.rb:50:in `block in execute'
  moped (2.0.0.rc1) lib/moped/node.rb:594:in `block (2 levels) in flush'

full log

当我将find更改为:

时,应用可行
  User.find(session[:user_id]['$oid'])

但规格失败了:

   1) ApplicationController current_user when current_user is nil and user_id stores in session finds and returns it from db
 Failure/Error: expect(subject.send(:current_user)).to eq user
 NoMethodError:
   undefined method `[]' for BSON::ObjectId('533fae9e616c6464a4010000'):BSON::ObjectId
 # ./app/controllers/application_controller.rb:7:in `current_user'
 # ./spec/controllers/application_controller_spec.rb:22:in `block (5 levels) in <top (required)>'

在我使用database_cleaner处理真正的数据库的规范中。所以,我猜都一样(但显然不是)

My gemfile

我已尝试为to_s according to this制作to_jsonuser_id,添加mongoid初始化文件with this,同时尝试使用{{}} {{} 1}} multi_json个版本 - 没有帮助。

我的应用程序控制器带有规范there

我几乎不希望有人可以提供帮助,考虑到之前这些棘手问题的结果,但无论如何,提前谢谢!

更新 测试失败:

moped

1 个答案:

答案 0 :(得分:1)

我之前遇到过类似的问题,问题是会话中BSON::ObjectId的json表示。正如您所发现的,调用to_s为我解决了这个问题。您需要确保该会话包含字符串格式的id。因此,无论何时将用户ID分配给会话,请致电to_s。尝试进行以下更改:

current_user=中的ApplicationController更改为:

def current_user=(user)
  @current_user = user
  session[:user_id] = user.try(:id).try(:to_s)
end

将规格更改为:

context "and user_id stores in session" do
  let(:user) { create(:user) }
  before { allow(subject).to receive(:session).and_return({ user_id: user.id.to_s }) }
  before { allow(User).to receive(:find).and_return(user) }

  it "finds and returns it from db" do
    expect(User).to receive(:find)
    expect(subject.send(:current_user)).to eq user
  end
end