为什么rails中的“where”查询返回不同的对象?

时间:2014-01-13 22:21:26

标签: ruby-on-rails ruby activerecord

我在我的应用中测试用户之间的聊天。我正在使用RSpec和FactoryGirl

未通过的测试:

it "creates a chat if one does not exist" do
  bob = create(:user, username: "bob")
  dan = create(:user, username: "dan")
  new_chat = Chat.create(user_id: @dan.id, chatted_user_id: bob.id)
  expect(Chat.where("chatted_user_id = ?", bob.id).first).to equal(new_chat)
end

失败消息说:

Failure/Error: expect(Chat.where("chatted_user_id = ?", bob.id).first).to equal(new_chat)

   expected #<Chat:70120833243920> => #<Chat id: 2, user_id: 2, chatted_user_id: 3>
        got #<Chat:70120833276240> => #<Chat id: 2, user_id: 2, chatted_user_id: 3>

   Compared using equal?, which compares object identity,
   but expected and actual are not the same object. Use
   `expect(actual).to eq(expected)` if you don't care about
   object identity in this example.

为什么我的查询返回不同的对象ID?

1 个答案:

答案 0 :(得分:2)

equal检查对象标识。您正在测试的对象是引用相同记录的两个对象(实例),但实际上它们与Ruby虚拟机的角度不同。

你应该使用

expect(Chat.where("chatted_user_id = ?", bob.id).first).to eq(new_chat)

为了更好地理解这个问题,请查看以下示例

2.0.0-p353 :001 > "foo".object_id
 => 70117320944040 
2.0.0-p353 :002 > "foo".object_id
 => 70117320962820 

这里我创建两个相同的字符串。它们是相同的,但不相同,因为它们实际上是两个不同的对象。

2.0.0-p353 :008 > "foo" == "foo"
 => true 
2.0.0-p353 :009 > "foo".equal? "foo"
 => false 

这是影响测试的同一问题。 equal检查object_id级别的两个对象是否实际相同。但你真正想知道的是它们是否是同一个记录。