覆盖ActiveRecord关系的count()方法可以吗? [英] Is overriding an ActiveRecord relation's count() method okay?
问题描述
假设我在Rails应用程序中具有以下关系:
Let's say I have the following relationship in my Rails app:
class Parent < ActiveRecord::Base
has_many :kids
end
class Kid < ActiveRecord::Base
belongs_to :parent
end
我希望父母成为能够查看他们的健谈孩子的列表,并使用该计数对列表进行分页。这是一种方法(我知道有点奇怪,请忍受):
I want parents to be able to see a list of their chatty kids, and use the count in paginating through that list. Here's a way to do that (I know it's a little odd, bear with me):
class Parent < ActiveRecord::Base
has_many :kids do
def for_chatting
proxy_association.owner.kids.where(:chatty => true)
end
end
end
但是!有些父母有数百万个孩子,即使数据库索引良好, p.kids.for_chatting.count
仍需要花费很长时间才能运行。我很确定这不能直接解决。但!我可以设置 Parent#chatty_kids_count
属性,并使用数据库触发器正确地对其进行更新。然后,我可以:
But! Some parents have millions of kids, and p.kids.for_chatting.count
takes too long to run, even with good database indexes. I'm pretty sure this cannot be directly fixed. But! I can set up a Parent#chatty_kids_count
attribute and keep it correctly updated with database triggers. Then, I can:
class Parent < ActiveRecord::Base
has_many :kids do
def for_chatting
parent = proxy_association.owner
kid_assoc = parent.kids.where(:chatty => true)
def kid_assoc.count
parent.chatty_kids_count
end
end
end
end
然后 parent.kids.for_chatting.count
使用缓存的计数,我的分页速度很快。
And then parent.kids.for_chatting.count
uses the cached count and my pagination is fast.
但是!在单例关联对象上覆盖 count()
会使呃,我太聪明了会使我的大脑大面积发光。
But! Overriding count()
on singleton association objects makes the uh-oh, I am being way too clever part of my brain light up big-time.
我觉得有一种更清晰的方法来解决这个问题。在那儿?还是这是是的,很奇怪,请评论一下您为什么这样做,这样会很好的情况?
I feel like there's a clearer way to approach this. Is there? Or is this a "yeah it's weird, leave a comment about why you're doing this and it'll be fine" kind of situation?
推荐答案
编辑:
我检查了will_paginate的代码,似乎它没有使用 count
方法AR关系,但我发现您可以为分页提供选项 total_entries
I checked the code of will_paginate, seems like it is not using count
method of AR relation, but i found that you can provide option total_entries
for paginate
@kids = @parent.kids.for_chatting.paginate(
page: params[:page],
total_entries: parent.chatty_kids_count
)
这不起作用
您可以使用包装器像这里的收藏
https://github.com/kaminari/kaminari / pull / 818#issuecomment-252788488 ,
只是覆盖计数方法。
This is not working
You can use wrapper for collection like here https://github.com/kaminari/kaminari/pull/818#issuecomment-252788488, just override count method.
class RelationWrapper < SimpleDelegator
def initialize(relation, total_count)
super(relation)
@total_count = total_count
end
def count
@total_count
end
end
# in a controller:
relation = RelationWrapper.new(@parent.kids.for_chatting, parent.chatty_kids_count)
这篇关于覆盖ActiveRecord关系的count()方法可以吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!