refactor: update popularity scope and controller logic

- Change `by_popularity` method in `City` model to use `start_time` for filtering views.
- Update `by_popularity` in `WeatherArt` model to limit results and incorporate the correct popularity calculation.
- Adjust `HomeController` to define `@popular_shuffle_arts` and `@latest_arts` with appropriate scopes.

These changes improve the accuracy of popularity retrieval for both cities and weather arts, simplifying the logic in the controller and leveraging updated model methods for performance.
This commit is contained in:
songtianlun 2025-02-12 17:54:57 +08:00
parent 940f1a8f76
commit 0a6926421f
5 changed files with 25 additions and 14 deletions

View File

@ -40,7 +40,7 @@ ActiveAdmin.register_page "Ahoy Dashboard" do
columns do
column do
panel "今日热门城市" do
table_for City.by_popularity(:today, 10) do
table_for City.by_popularity(:day, 10) do
column("城市") { |city| link_to(city.name, admin_city_path(city)) }
column("访问量") { |city| city.view_count }
end

View File

@ -1,6 +1,7 @@
class HomeController < ApplicationController
def index
@latest_arts = WeatherArt.includes(:city).order(created_at: :desc).limit(20).shuffle.last(10)
@popular_shuffle_arts = WeatherArt.by_popularity(10).shuffle.last(6)
@latest_arts = WeatherArt.latest(12)
@featured_arts = WeatherArt.includes(:city).order(created_at: :desc).limit(5)
set_meta_tags(
title: "AI-Generated Weather Art",

View File

@ -25,18 +25,18 @@ class City < ApplicationRecord
# 在 City 模型中
scope :by_popularity, ->(period = :year, limit = 100) {
# 根据时间周期确定时间范围
time_range =
start_time =
case period.to_sym
when :today
Time.current.beginning_of_day..Time.current.end_of_day
when :day
1.day.ago
when :week
Time.current.beginning_of_week..Time.current.end_of_week
1.week.ago
when :month
Time.current.beginning_of_month..Time.current.end_of_month
1.month.ago
when :year
Time.current.beginning_of_year..Time.current.end_of_year
1.year.ago
else
Time.current.beginning_of_year..Time.current.end_of_year
1.year.ago
end
# 根据数据库类型构建不同的查询
@ -45,14 +45,14 @@ class City < ApplicationRecord
LEFT JOIN ahoy_events ON
json_extract(ahoy_events.properties, '$.city_id') = cities.id
AND json_extract(ahoy_events.properties, '$.event_type') = 'city_view'
AND ahoy_events.time BETWEEN '#{time_range.begin}' AND '#{time_range.end}'
AND ahoy_events.time > '#{start_time}'
SQL
else
joins(<<-SQL.squish)
LEFT JOIN ahoy_events ON
(ahoy_events.properties::jsonb->>'city_id')::integer = cities.id
AND ahoy_events.properties::jsonb->>'event_type' = 'city_view'
AND ahoy_events.time BETWEEN '#{time_range.begin}' AND '#{time_range.end}'
AND ahoy_events.time > '#{start_time}'
SQL
end

View File

@ -12,19 +12,23 @@ class WeatherArt < ApplicationRecord
validates :weather_date, presence: true
validates :city_id, presence: true
scope :by_popularity, -> {
scope :latest, ->(limit: 100) {
order(created_at: :desc).limit(limit)
}
scope :by_popularity, ->(limit: 100) {
if ActiveRecord::Base.connection.adapter_name.downcase == "sqlite"
joins("LEFT JOIN ahoy_events ON json_extract(ahoy_events.properties, '$.weather_art_id') = weather_arts.id
AND json_extract(ahoy_events.properties, '$.event_type') = 'weather_art_view'")
.group("weather_arts.id")
.select("weather_arts.*, COUNT(ahoy_events.id) as visit_count")
.order("visit_count DESC")
.order("visit_count DESC").limit(limit)
else
joins("LEFT JOIN ahoy_events ON (ahoy_events.properties::jsonb->>'weather_art_id')::integer = weather_arts.id
AND ahoy_events.properties::jsonb->>'event_type' = 'weather_art_view'")
.group("weather_arts.id")
.select("weather_arts.*, COUNT(ahoy_events.id) as visit_count")
.order("visit_count DESC")
.order("visit_count DESC").limit(limit)
end
}

View File

@ -5,6 +5,12 @@ class BatchGenerateWeatherArtsWorker
SLEEP_DURATION = 120.seconds
BATCH_SIZE = 20
module ProcessType
DO_NOTHING = 0
GET_WEATHER_WITH_GENERATE_AI_ART = 1
GET_WEATHER_ONLY = 2
end
def perform(*args)
start_time = Time.current
cities_to_process = get_eligible_cities.shuffle.take(BATCH_SIZE)