5

ユーザーが「オファー」に関するメッセージを互いに送信できるようにするアプリケーションを作成しています。

少し手間を省いて、 Mailboxer gemを使用しようと思いました。

私は RSpec を使用したテスト駆動開発アプローチに従っています。オファーごとに 1つのみConversationが許可されるようにするテストを作成しています。belongs_to2 人の異なるユーザー (オファーを行ったユーザーとオファーを受け取ったユーザー) のオファー。

これが私の失敗したテストです:

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_userreceive_user にメッセージを 2 回送信します。は次の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メッセージが送信され、2 人のユーザー間で会話が作成されます。

2 回目の繰り返しでは、最初の繰り返しで作成された会話が返され、ユーザーはその会話に返信しますが、新しい会話は作成されません。

これはすべて機能しますが、テストが失敗し、その理由がわかりません!

上記で指定した場所のコードにこじ開けバインディングを配置すると、何が起こっているのかを調べることができます...今、これをなぞなぞにします:

重量ルビー

self.mailbox.conversations[0]Conversationインスタンスを返します

self.mailbox.conversations[1]戻り値nil

self.mailbox.conversations1 つのオブジェクトを含むコレクションを明確に示しています。

self.mailbox.conversations.count2を返す?!

そこで何が起こっているのですか?countメソッドが正しくなく、テストが失敗しています...

私は何が欠けていますか?それともこれはバグですか?

編集

offer.conversation次のようになります。

  def conversation
    Conversation.where({subject: conversation_subject}).last
  end

offer.conversation_subject:

  def conversation_subject
    "offer-#{self.id}"
  end

編集 2 - pry で最初と 2 番目の反復を表示する

wtfルビー2

また...

Conversation.all.count1を返します!

と:

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

私が間違っていることはわかりません!これを回避するためにテストを作り直すかもしれません。または、宝石を捨てて自分で書いてください。

4

5 に答える 5

9

このRails 3 を参照してください: Relation.count と Relation.all.count の違い

要するにselect、クエリに count を適用すると、Rails は列 (複数の場合) を無視します。それの訳は

SQL の COUNT は、1 つ以下の列のみをパラメーターとして許可します。

コードからMailbox

 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.*')カウントします。基本的に、その中に重複するの数をカウントします。joinreceiptsreceiptsconversations

一方、 はself.mailbox.conversations.all.count最初に を適用してレコードをselect取得し、それを一意conversationsにしてからカウントします。

self.mailbox.conversations.all == self.mailbox.conversationsどちらもselectでdbを照会するためです。

問題を解決するには、sending_user.mailbox.conversations.all.countまたはsending_user.mailbox.conversations.group('conversations.id').length

于 2013-09-22T22:31:51.647 に答える
0

の結果はmailbox.conversations、最初の呼び出しの後にキャッシュされます。リロードするには、次のように記述しますmailbox.conversations(true)

于 2013-09-23T08:04:55.307 に答える