songtianlun
dd6cd0451d
- Integrate Ahoy gem for tracking user events and visits - Create models for Ahoy events and visits - Implement admin interfaces for managing events and visits - Add background job for cleaning up old analytics data - Update application controller and other relevant controllers to track specific actions This commit implements a comprehensive event tracking system that logs user interactions within the application. Additionally, it includes mechanisms for managing and cleaning historical visit and event data, ensuring efficient data handling.
97 lines
2.9 KiB
Ruby
97 lines
2.9 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->>'city_id')::integer = cities.id
|
|
AND ahoy_events.properties->>'event_type' = 'city_view'")
|
|
.group("cities.id")
|
|
.select("cities.*, COUNT(ahoy_events.id) as visit_count")
|
|
.order("visit_count DESC")
|
|
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->>'event_type' = 'city_view' AND (properties->>'city_id')::integer = ?", self.id).count
|
|
end
|
|
end
|
|
end
|