我正在编写一个应用程序,允许用户发送有关“要约”的消息。
我以为自己可以省下一些工作,并使用Mailboxer gem。
我正在使用RSpec进行测试驱动的开发方法。我正在编写一个测试,该测试应确保每个要约仅允许一个Conversation
。要约belongs_to
是两个不同的用户(提出要约的用户和收到要约的用户)。
这是我的不及格测试:
describe "after a message is sent to the same user twice" do
before do
2.times { sending_user.message_user_regarding_offer! offer, receiving_user, random_string }
end
specify { sending_user.mailbox.conversations.count.should == 1 }
end
因此,在测试运行之前,用户
sending_user
将消息两次发送给receive_user。 message_user_regarding_offer!
看起来像这样:def message_user_regarding_offer! offer, receiver, body
conversation = offer.conversation
if conversation.nil?
self.send_message(receiver, body, offer.conversation_subject)
else
self.reply_to_conversation(conversation, body)
# I put a binding.pry here to examine in console
end
offer.create_activity key: PublicActivityKeys.message_received, owner: self, recipient: receiver
end
在测试的第一次迭代中(发送第一条消息时),
conversation
变量为nil
,因此发送了一条消息,并在两个用户之间创建了对话。在第二次迭代中,将返回在第一次迭代中创建的对话,并且用户会回复该对话,但是不会创建新的对话。
所有这些都可以,但是测试失败了,我不明白为什么!
当我在上面指定的位置的代码中放置 pry 绑定(bind)时,我可以检查发生了什么...现在让我感到困惑:
self.mailbox.conversations[0]
返回一个Conversation
实例self.mailbox.conversations[1]
返回nil
self.mailbox.conversations
清楚地显示了一个包含一个对象的集合。self.mailbox.conversations.count
返回2?那里发生了什么事?
count
方法不正确,我的测试失败了...我想念什么?还是这是一个错误?
编辑
offer.conversation
看起来像这样: def conversation
Conversation.where({subject: conversation_subject}).last
end
和
offer.conversation_subject
: def conversation_subject
"offer-#{self.id}"
end
编辑2-在pry 中显示第一次和第二次迭代
还...
Conversation.all.count
返回1!和:
Conversation.all == self.mailbox.conversations
返回true
和
Conversation.all.count == self.mailbox.conversations.count
返回false
如果数组相等怎么办?我不知道这是怎么回事,现在已经花了很多时间。认为这是一个错误吗?
编辑3
从Mailboxer gem的来源...
def conversations(options = {})
conv = Conversation.participant(@messageable)
if options[:mailbox_type].present?
case options[:mailbox_type]
when 'inbox'
conv = Conversation.inbox(@messageable)
when 'sentbox'
conv = Conversation.sentbox(@messageable)
when 'trash'
conv = Conversation.trash(@messageable)
when 'not_trash'
conv = Conversation.not_trash(@messageable)
end
end
if (options.has_key?(:read) && options[:read]==false) || (options.has_key?(:unread) && options[:unread]==true)
conv = conv.unread(@messageable)
end
conv
end
此处提供
reply_to_convesation
代码-> http://rubydoc.info/gems/mailboxer/frames。只是看不到我在做什么错!可能需要重新测试以解决此问题。或抛弃 gem ,然后写我自己的 gem 。
最佳答案
看到这个Rails 3: Difference between Relation.count and Relation.all.count
简而言之,当您将count应用于查询时,Rails会忽略select
列(如果有多个)。这是因为
来自Mailbox
code
scope :participant, lambda {|participant|
select('DISTINCT conversations.*').
where('notifications.type'=> Message.name).
order("conversations.updated_at DESC").
joins(:receipts).merge(Receipt.recipient(participant))
}
self.mailbox.conversations.count
忽略select('DISTINCT conversations.*')
并使用join
对receipts
表进行计数,实际上是对其中重复receipts
的conversations
的数目进行计数。另一方面,
self.mailbox.conversations.all.count
首先获取应用select
的记录,该记录将获得唯一的conversations
,然后对其进行计数。self.mailbox.conversations.all == self.mailbox.conversations
,因为他们两个都用select查询数据库。要解决您的问题,您可以使用
sending_user.mailbox.conversations.all.count
或sending_user.mailbox.conversations.group('conversations.id').length
关于ruby-on-rails - Ruby on Rails-ActiveRecord::Relation计数方法错误?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/18905700/