我有一个用户可以查看的模型列表,如果他们认为某个特定项目不合适,他们可能会标记它。我想排除标记达到某个阈值的项目,但我不确定如何完成此操作,因为标记计数不是我模型的一部分。
我知道我可以使用以下内容来获取模型的标记数:
Model.flaggings.count
但是我该如何过滤呢?我尝试以一种我认为可能无济于事的方式添加范围:
def self.appropriate
return unless self.flaggings.count > 5
end
我有一个用户可以查看的模型列表,如果他们认为某个特定项目不合适,他们可能会标记它。我想排除标记达到某个阈值的项目,但我不确定如何完成此操作,因为标记计数不是我模型的一部分。
我知道我可以使用以下内容来获取模型的标记数:
Model.flaggings.count
但是我该如何过滤呢?我尝试以一种我认为可能无济于事的方式添加范围:
def self.appropriate
return unless self.flaggings.count > 5
end
你也可以
1)缓存标记计数,并在模型中对其进行过滤。这是一个 counter_cache,您可以手动连接它或让 rails 为您保持直线。
2)添加范围以过滤计数。这个答案是相关的:How can I find records by "count" of association using rails and mongoid? . 这种方法使得添加其他范围变得更加困难。
Persoanlly,我喜欢这样做:
3) 将“不合适”的模型项的所有 id 缓存在另一个地方(例如 Memcache 或 Redis),并使用此 ID 列表过滤范围内的结果。
Model.appropriate.where(...)
“适当的”范围方法将从缓存中获取值。
class Model < ActiveRecord::Base
def self.appropriate
where('models.id not in', Model.inappropriate_ids)
end
def self.inappropriate_ids
Rails.cache.fetch('appropriate_model_ids'){
# Get all ids of appropriate items in a single array.
# Something like this
Flagging.having('count(*) > 5').count(:group => :model_id).keys
}
end
end
您可以使用 having 子句来完成此操作。
class Model < ActiveRecord::Base
has_many: :flaggings
def self.appropriate_items
select("models.*, count(flaggings.id")).joins(:flaggings)group("models.id, flaggings.model_id").having("count(flaggings.id) < 5")
end
end