我正在构建一个具有以下模型的 Rails 应用程序:
# vote.rb
class Vote < ApplicationRecord
belongs_to :person
belongs_to :show
scope :fulfilled, -> { where(fulfilled: true) }
scope :unfulfilled, -> { where(fulfilled: false) }
end
# person.rb
class Person < ApplicationRecord
has_many :votes, dependent: :destroy
def self.order_by_votes(show = nil)
count = 'nullif(votes.fulfilled, true)'
count = "case when votes.show_id = #{show.id} AND NOT votes.fulfilled then 1 else null end" if show
people = left_joins(:votes).group(:id).uniq!(:group)
people = people.select("people.*, COUNT(#{count}) AS people.vote_count")
people.order('people.vote_count DESC')
end
end
背后的想法order_by_votes
是People
按未完成的票数排序,要么计算所有选票,要么只计算与给定Show
.
当我针对 SQLite 进行测试时,这似乎工作正常。但是当我切换到 Postgres 时,我收到此错误:
Error:
PeopleControllerIndexTest#test_should_get_previously_on_show:
ActiveRecord::StatementInvalid: PG::UndefinedColumn: ERROR: column people.vote_count does not exist
LINE 1: ...s"."show_id" = $1 GROUP BY "people"."id" ORDER BY people.vot...
^
如果我使用 转储 SQL @people.to_sql
,这就是我得到的:
SELECT people.*, COUNT(nullif(votes.fulfilled, true)) AS people.vote_count FROM "people" LEFT OUTER JOIN "votes" ON "votes"."person_id" = "people"."id" GROUP BY "people "."id" ORDER BY people.vote_count DESC
为什么这在 Postgres 上失败,但在 SQLite 上工作?我应该怎么做才能让它在 Postgres 上工作?
(PS:我people.vote_count
用一个点命名了该字段,所以我可以在我的视图中访问它而无需执行另一个 SQL 查询来实际查看视图中每个人的投票计数(不确定这是否有效)但我得到了即使我简单地命名该字段,也会出现同样的错误vote_count
。)
(PS2:我最近添加了.uniq!(:group)
因为 Rails 6.2 的一些弃用警告,但我找不到任何文档,所以我不确定我做对了,如果没有那部分,错误仍然存在。)
感谢所有的评论和答案,我终于找到了一个解决方案,我认为这是解决这个问题的最佳方法。
首先,当我调用pagy
它试图通过附加.count(:all)
. 这就是导致错误的原因。解决方案是不在中创建“字段”select()
并在.order()
.
所以这是正确的代码:
def self.order_by_votes(show = nil)
count = if show
"case when votes.show_id = #{show.id} AND NOT votes.fulfilled then 1 else null end"
else
'nullif(votes.fulfilled, true)'
end
left_joins(:votes).group(:id)
.uniq!(:group)
.select("people.*, COUNT(#{count}) as vote_count")
.order(Arel.sql("COUNT(#{count}) DESC"))
end
这根据未完成的投票数对人数进行排序,能够仅计算给定节目的投票数,并且它适用于pagy()
,pagy_arel()
在我的情况下更适合,因此可以正确地对结果进行分页.
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句