Ruby on Rails的 - 的ActiveRecord ::关系计数法是错误的? [英] Ruby on Rails - ActiveRecord::Relation count method is wrong?
问题描述
我正在写一个应用程序,允许用户发送一个关于一个'报价'的另一个消息。
我想我会拯救自己的一些工作,并使用 Mailboxer 的宝石。
我在与RSpec的测试驱动的开发方法。我正在写一个测试,应确保只有一个会话
元的报价是允许的。 belongs_to的
要约两个不同的用户(即提出收购用户,并且所收到的报价的用户)。
下面是我失败的测试:
说明后,消息被发送到同一个用户两次吗
之前做
2.times {sending_user.message_user_regarding_offer!报价,receiving_user,random_string}
结束
指定{sending_user.mailbox.conversations.count.should == 1}
结束
所以测试运行用户之前 sending_user
将消息发送到receiving_user的两倍。 !本 message_user_regarding_offer
是这样的:
高清message_user_regarding_offer!报价,接收器,体
谈话= offer.conversation
如果conversation.nil?
self.send_message(接收机,身体,offer.conversation_subject)
其他
self.reply_to_conversation(谈话,体)
#我把binding.pry这里查看控制台
结束
offer.create_activity键:PublicActivityKeys.message_received,老板:自我,收件人:接收器
结束
在测试中的第一次迭代(当第一条消息被发送)的会话
变量零
因此,一个消息发送和两个用户之间建立一个对话。
在第二次迭代中的第一次迭代中创建的会话返回并且用户答复该谈话,但不创建一个新的对话。
这一切工作,但测试失败,我不明白为什么!
当我把撬在code上面我指定的可以检查是怎么回事的位置绑定...现在谜语我:
self.mailbox.conversations [0]
返回会话
实例
self.mailbox.conversations [1]
返回零
self.mailbox.conversations
清楚地显示了包含一个对象的集合。
self.mailbox.conversations.count
返回2?!
这是怎么回事呢?在计数
方法是不正确的,我的测试失败......
我在想什么?或者这是一个错误?!
修改
offer.conversation
是这样的:
高清通话
Conversation.where({主题:conversation_subject})。最后
结束
和 offer.conversation_subject
:
高清conversation_subject
报价 - #{self.id}
结束
编辑2 - 显示在第一和第二次迭代撬
另外...
Conversation.all.count
返回1!
和
Conversation.all == self.mailbox.conversations
返回真
和
Conversation.all.count == self.mailbox.conversations.count
返回假
这怎么可能,如果数组是一样的吗?我不知道现在发生了什么事情就到这里,吹小时这一点。认为这是一个错误?!
修改3
从Mailboxer宝石的来源......
高清通话(选项= {})
CONV = Conversation.participant(@messageable)
如果选项[:mailbox_type]。present?
案例选项[:mailbox_type]
当收件箱
CONV = Conversation.inbox(@messageable)
当发件箱
CONV = Conversation.sentbox(@messageable)
当垃圾
CONV = Conversation.trash(@messageable)
当not_trash
CONV = Conversation.not_trash(@messageable)
结束
结束
如果(options.has_key(:读取)及和放大器;选项?[:阅读] ==假)|| (options.has_key(:未读)及和放大器;选项?[:未读] ==真)
CONV = conv.unread(@messageable)
结束
CONV
结束
在 reply_to_convesation
code是可以在这里 - >的 http://rubydoc.info/gems/mailboxer/frames 。
只是不明白我在做什么错了!可能返工我的测试来解决这个问题。或者沟宝石,写我自己的。
看到这样的<一个href="http://stackoverflow.com/questions/5092745/rails-3-difference-between-relation-count-and-relation-all-count">Rails 3:Relation.count和Relation.all.count 的区别
在短暂的Rails忽略选择
列(如果有多个),当你申请数量的查询。这是因为
SQL的COUNT只允许一个或更少的列作为参数。</ P>
在邮箱
的 code
范围:参加者的lambda {|参与者|
选择(DISTINCT对话。*)。
其中,('notifications.type'=&GT; Message.name)。
为了(conversations.updated_at DESC)。
加入(:收益).merge(Receipt.recipient(参与者))
}
self.mailbox.conversations.count
忽略选择(DISTINCT对话。*')
和计数加入
表收入
的收益基本计算数
与复制它对话
。
在另一方面, self.mailbox.conversations.all.count
首先获得应用记录的选择
,其中获得独特的对话
然后计算它。
self.mailbox.conversations.all == self.mailbox.conversations
,因为他们两人查询与选择的分贝。
要解决你的问题,你可以使用 sending_user.mailbox.conversations.all.count
或 sending_user.mailbox.conversations.group(对话。 ID)。长度
I'm writing an application that allows users to send one another messages about an 'offer'.
I thought I'd save myself some work and use the Mailboxer gem.
I'm following a test driven development approach with RSpec. I'm writing a test that should ensure that only one Conversation
is allowed per offer. An offer belongs_to
two different users (the user that made the offer, and the user that received the offer).
Here is my failing test:
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
So before the test runs a user sending_user
sends a message to the receiving_user twice. The message_user_regarding_offer!
looks like this:
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
On the first iteration in the test (when the first message is sent) the conversation
variable is nil
therefore a message is sent and a conversation is created between the two users.
On the second iteration the conversation created in the first iteration is returned and the user replies to that conversation, but a new conversation isn't created.
This all works, but the test fails and I cannot understand why!
When I place a pry binding in the code in the location specified above I can examine what is going on... now riddle me this:
self.mailbox.conversations[0]
returns a Conversation
instance
self.mailbox.conversations[1]
returns nil
self.mailbox.conversations
clearly shows a collection containing ONE object.
self.mailbox.conversations.count
returns 2?!
What is going on there? the count
method is incorrect and my test is failing...
What am I missing? Or is this a bug?!
EDIT
offer.conversation
looks like this:
def conversation
Conversation.where({subject: conversation_subject}).last
end
and offer.conversation_subject
:
def conversation_subject
"offer-#{self.id}"
end
EDIT 2 - Showing the first and second iteration in pry
Also...
Conversation.all.count
returns 1!
and:
Conversation.all == self.mailbox.conversations
returns true
and
Conversation.all.count == self.mailbox.conversations.count
returns false
How can that be if the arrays are equal? I don't know what's going on here, blown hours on this now. Think it's a bug?!
EDIT 3
From the source of the 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
The reply_to_convesation
code is available here -> http://rubydoc.info/gems/mailboxer/frames.
Just can't see what I'm doing wrong! Might rework my tests to get around this. Or ditch the gem and write my own.
see this Rails 3: Difference between Relation.count and Relation.all.count
In short Rails ignores the select
columns (if more than one) when you apply count to the query. This is because
SQL's COUNT allows only one or less columns as parameters.
From 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
ignores the select('DISTINCT conversations.*')
and counts the join
table with receipts
, essentially counting number of receipts
with duplicate conversations
in it.
On the other hand, self.mailbox.conversations.all.count
first gets the records applying the select
, which gets unique conversations
and then counts it.
self.mailbox.conversations.all == self.mailbox.conversations
since both of them query the db with the select.
To solve your problem you can use sending_user.mailbox.conversations.all.count
or sending_user.mailbox.conversations.group('conversations.id').length
这篇关于Ruby on Rails的 - 的ActiveRecord ::关系计数法是错误的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!