我正在编写一个应用程序,允许用户发送有关“要约”的消息。

我以为自己可以省下一些工作,并使用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]返回nilself.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.*')并使用joinreceipts表进行计数,实际上是对其中重复receiptsconversations的数目进行计数。

另一方面,self.mailbox.conversations.all.count首先获取应用select的记录,该记录将获得唯一的conversations,然后对其进行计数。
self.mailbox.conversations.all == self.mailbox.conversations,因为他们两个都用select查询数据库。

要解决您的问题,您可以使用sending_user.mailbox.conversations.all.countsending_user.mailbox.conversations.group('conversations.id').length

关于ruby-on-rails - Ruby on Rails-ActiveRecord::Relation计数方法错误?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/18905700/

10-16 02:27