- Simplify query for most popular inactive cities in City model - Minor layout changes in Admin Dashboards for Ahoy and Sidekiq tasks This refactoring improves code organization, reducing complexity in the City model and making it easier to read. Additionally, the Admin dashboard layouts have been simplified for a better user experience.
132 lines
4.6 KiB
Ruby
132 lines
4.6 KiB
Ruby
class City < ApplicationRecord
|
|
extend FriendlyId
|
|
friendly_id :slug_candidates, use: :slugged
|
|
belongs_to :country
|
|
|
|
has_many :weather_arts, dependent: :destroy
|
|
|
|
has_many :visits, class_name: "Ahoy::Visit", foreign_key: :city_id
|
|
has_many :events, class_name: "Ahoy::Event", foreign_key: :city_id
|
|
|
|
delegate :region, to: :country
|
|
|
|
validates :name, presence: true
|
|
validates :latitude, presence: true
|
|
validates :longitude, presence: true
|
|
|
|
delegate :region, to: :country
|
|
|
|
scope :by_region, ->(region_id) { joins(:country).where(countries: { region_id: region_id }) }
|
|
scope :by_country, ->(country_id) { where(country_id: country_id) }
|
|
scope :active, -> { where(active: true) }
|
|
|
|
scope :by_popularity, -> {
|
|
if ActiveRecord::Base.connection.adapter_name.downcase == "sqlite"
|
|
joins("LEFT JOIN ahoy_events ON json_extract(ahoy_events.properties, '$.city_id') = cities.id
|
|
AND json_extract(ahoy_events.properties, '$.event_type') = 'city_view'")
|
|
.group("cities.id")
|
|
.select("cities.*, COUNT(ahoy_events.id) as visit_count")
|
|
.order("visit_count DESC")
|
|
else
|
|
joins("LEFT JOIN ahoy_events ON (ahoy_events.properties::jsonb->>'city_id')::integer = cities.id
|
|
AND ahoy_events.properties::jsonb->>'event_type' = 'city_view'")
|
|
.group("cities.id")
|
|
.select("cities.*, COUNT(ahoy_events.id) as visit_count")
|
|
.order("visit_count DESC")
|
|
end
|
|
}
|
|
|
|
scope :least_popular_active, -> {
|
|
if ActiveRecord::Base.connection.adapter_name.downcase == "sqlite"
|
|
active
|
|
.joins("LEFT JOIN ahoy_events ON json_extract(ahoy_events.properties, '$.city_id') = cities.id
|
|
AND json_extract(ahoy_events.properties, '$.event_type') = 'city_view'")
|
|
.group("cities.id")
|
|
.select("cities.*, COUNT(ahoy_events.id) as visit_count")
|
|
.order("visit_count ASC, cities.name ASC")
|
|
else
|
|
active
|
|
.joins("LEFT JOIN ahoy_events ON (ahoy_events.properties::jsonb->>'city_id')::integer = cities.id
|
|
AND ahoy_events.properties::jsonb->>'event_type' = 'city_view'")
|
|
.group("cities.id")
|
|
.select("cities.*, COUNT(ahoy_events.id) as visit_count")
|
|
.order("visit_count ASC, cities.name ASC")
|
|
end
|
|
}
|
|
scope :most_popular_inactive, -> {
|
|
if ActiveRecord::Base.connection.adapter_name.downcase == "sqlite"
|
|
where(active: false)
|
|
.joins("LEFT JOIN ahoy_events ON json_extract(ahoy_events.properties, '$.city_id') = cities.id
|
|
AND json_extract(ahoy_events.properties, '$.event_type') = 'city_view'")
|
|
.group("cities.id")
|
|
.select("cities.*, COUNT(ahoy_events.id) as visit_count")
|
|
.order("COUNT(ahoy_events.id) DESC, cities.name ASC")
|
|
else
|
|
where(active: false)
|
|
.joins("LEFT JOIN ahoy_events ON (ahoy_events.properties::jsonb->>'city_id')::integer = cities.id
|
|
AND ahoy_events.properties::jsonb->>'event_type' = 'city_view'")
|
|
.group("cities.id")
|
|
.select("cities.*, COUNT(ahoy_events.id) as visit_count")
|
|
.order("COUNT(ahoy_events.id) DESC, cities.name ASC")
|
|
end
|
|
}
|
|
|
|
|
|
def to_s
|
|
name
|
|
end
|
|
|
|
def slug_candidates
|
|
[
|
|
:name,
|
|
[ :country, :name ]
|
|
]
|
|
end
|
|
|
|
def localized_name
|
|
I18n.t("cities.#{name.parameterize.underscore}")
|
|
end
|
|
|
|
def full_name
|
|
"#{name}, #{country}"
|
|
end
|
|
|
|
def should_generate_new_friendly_id?
|
|
name_changed? || super
|
|
end
|
|
|
|
def self.ransackable_associations(auth_object = nil)
|
|
[ "weather_arts" ]
|
|
end
|
|
|
|
def self.ransackable_attributes(auth_object = nil)
|
|
[ "active", "country_id", "created_at", "id", "id_value", "last_image_generation", "last_weather_fetch", "latitude", "longitude", "name", "priority", "region", "slug", "timezone", "updated_at" ]
|
|
end
|
|
|
|
def last_weather_fetch
|
|
# latest_weather_art&.created_at
|
|
Rails.cache.fetch("city/#{id}/last_weather_fetch", expires_in: 1.hour) do
|
|
latest_weather_art&.created_at
|
|
end
|
|
end
|
|
|
|
def last_image_generation
|
|
# latest_weather_art&.image&.created_at
|
|
Rails.cache.fetch("city/#{id}/last_image_generation", expires_in: 1.hour) do
|
|
latest_weather_art&.image&.created_at
|
|
end
|
|
end
|
|
|
|
def latest_weather_art
|
|
weather_arts.order(weather_date: :desc).first
|
|
end
|
|
|
|
def view_count
|
|
if ActiveRecord::Base.connection.adapter_name.downcase == "sqlite"
|
|
Ahoy::Event.where("json_extract(properties, '$.event_type') = 'city_view' AND json_extract(properties, '$.city_id') = ?", self.id).count
|
|
else
|
|
Ahoy::Event.where("properties::jsonb->>'event_type' = 'city_view' AND (properties::jsonb->>'city_id')::integer = ?", self.id).count
|
|
end
|
|
end
|
|
end
|