diff --git a/app/models/concerns/ranked_trend.rb b/app/models/concerns/ranked_trend.rb new file mode 100644 index 000000000..add36afb0 --- /dev/null +++ b/app/models/concerns/ranked_trend.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +module RankedTrend + extend ActiveSupport::Concern + + included do + scope :by_rank, -> { order(rank: :desc) } + scope :ranked_below, ->(value) { where(rank: ..value) } + end + + class_methods do + def recalculate_ordered_rank + connection + .exec_update(<<~SQL.squish) + UPDATE #{table_name} + SET rank = inner_ordered.calculated_rank + FROM ( + SELECT id, row_number() OVER w AS calculated_rank + FROM #{table_name} + WINDOW w AS ( + PARTITION BY language + ORDER BY score DESC + ) + ) inner_ordered + WHERE #{table_name}.id = inner_ordered.id + SQL + end + end +end diff --git a/app/models/preview_card_trend.rb b/app/models/preview_card_trend.rb index 018400dfa..da2ea2f8c 100644 --- a/app/models/preview_card_trend.rb +++ b/app/models/preview_card_trend.rb @@ -12,6 +12,8 @@ # language :string # class PreviewCardTrend < ApplicationRecord + include RankedTrend + belongs_to :preview_card scope :allowed, -> { where(allowed: true) } end diff --git a/app/models/status_trend.rb b/app/models/status_trend.rb index b0f1b6942..807efec0f 100644 --- a/app/models/status_trend.rb +++ b/app/models/status_trend.rb @@ -14,6 +14,8 @@ # class StatusTrend < ApplicationRecord + include RankedTrend + belongs_to :status belongs_to :account diff --git a/app/models/trends/links.rb b/app/models/trends/links.rb index b4eae9f70..76e50aa7a 100644 --- a/app/models/trends/links.rb +++ b/app/models/trends/links.rb @@ -81,12 +81,12 @@ class Trends::Links < Trends::Base # Now that all trends have up-to-date scores, and all the ones below the threshold have # been removed, we can recalculate their positions - PreviewCardTrend.connection.exec_update('UPDATE preview_card_trends SET rank = t0.calculated_rank FROM (SELECT id, row_number() OVER w AS calculated_rank FROM preview_card_trends WINDOW w AS (PARTITION BY language ORDER BY score DESC)) t0 WHERE preview_card_trends.id = t0.id') + PreviewCardTrend.recalculate_ordered_rank end def request_review PreviewCardTrend.pluck('distinct language').flat_map do |language| - score_at_threshold = PreviewCardTrend.where(language: language, allowed: true).order(rank: :desc).where('rank <= ?', options[:review_threshold]).first&.score || 0 + score_at_threshold = PreviewCardTrend.where(language: language, allowed: true).by_rank.ranked_below(options[:review_threshold]).first&.score || 0 preview_card_trends = PreviewCardTrend.where(language: language, allowed: false).joins(:preview_card) preview_card_trends.filter_map do |trend| diff --git a/app/models/trends/statuses.rb b/app/models/trends/statuses.rb index c47fb8427..9be6eb13a 100644 --- a/app/models/trends/statuses.rb +++ b/app/models/trends/statuses.rb @@ -74,12 +74,12 @@ class Trends::Statuses < Trends::Base # Now that all trends have up-to-date scores, and all the ones below the threshold have # been removed, we can recalculate their positions - StatusTrend.connection.exec_update('UPDATE status_trends SET rank = t0.calculated_rank FROM (SELECT id, row_number() OVER w AS calculated_rank FROM status_trends WINDOW w AS (PARTITION BY language ORDER BY score DESC)) t0 WHERE status_trends.id = t0.id') + StatusTrend.recalculate_ordered_rank end def request_review StatusTrend.pluck('distinct language').flat_map do |language| - score_at_threshold = StatusTrend.where(language: language, allowed: true).order(rank: :desc).where('rank <= ?', options[:review_threshold]).first&.score || 0 + score_at_threshold = StatusTrend.where(language: language, allowed: true).by_rank.ranked_below(options[:review_threshold]).first&.score || 0 status_trends = StatusTrend.where(language: language, allowed: false).joins(:status).includes(status: :account) status_trends.filter_map do |trend|