Merge branch 'fix/image-upload' into feat/image-upload
This commit is contained in:
@@ -29,7 +29,9 @@ class Event < ApplicationRecord
|
||||
|
||||
|
||||
# === Callbacks ===
|
||||
before_validation :generate_slug, if: :should_generate_slug?
|
||||
before_validation :geocode_address, if: :should_geocode_address?
|
||||
before_update :handle_image_replacement, if: :image_attached?
|
||||
|
||||
# Validations for Event attributes
|
||||
# Basic information
|
||||
@@ -67,19 +69,98 @@ class Event < ApplicationRecord
|
||||
|
||||
# === Instance Methods ===
|
||||
|
||||
# Get image for display - handles both uploaded files and URLs
|
||||
def event_image_variant(size = :medium)
|
||||
if image.attached?
|
||||
case size
|
||||
when :large
|
||||
image.variant(resize_to_limit: [1200, 630])
|
||||
when :medium
|
||||
image.variant(resize_to_limit: [800, 450])
|
||||
when :small
|
||||
image.variant(resize_to_limit: [400, 225])
|
||||
else
|
||||
image
|
||||
# Generate SEO-friendly slug from name, venue name, and city
|
||||
def generate_slug
|
||||
return if name.blank? && venue_name.blank? && venue_address.blank?
|
||||
|
||||
# Extract city from venue address
|
||||
city = extract_city_from_address(venue_address)
|
||||
|
||||
# Build slug parts
|
||||
slug_parts = []
|
||||
slug_parts << name if name.present?
|
||||
slug_parts << venue_name if venue_name.present?
|
||||
slug_parts << city if city.present?
|
||||
|
||||
# Generate slug using Rails' parameterize
|
||||
slug_value = slug_parts.join("-").parameterize
|
||||
|
||||
# Ensure minimum length
|
||||
if slug_value.length < 3
|
||||
slug_value = "event-#{Time.current.to_i}".parameterize
|
||||
end
|
||||
|
||||
# Make sure slug is unique
|
||||
base_slug = slug_value
|
||||
counter = 1
|
||||
while Event.where.not(id: id).where(slug: slug_value).exists?
|
||||
slug_value = "#{base_slug}-#{counter}".parameterize
|
||||
counter += 1
|
||||
end
|
||||
|
||||
self.slug = slug_value
|
||||
end
|
||||
|
||||
# Check if slug should be generated
|
||||
def should_generate_slug?
|
||||
# Generate slug if it's blank or if it's a new record
|
||||
slug.blank? || new_record?
|
||||
end
|
||||
|
||||
# Extract city from address
|
||||
def extract_city_from_address(address)
|
||||
return "" if address.blank?
|
||||
|
||||
# Look for French postal code pattern (5 digits) + city
|
||||
match = address.match(/(\d{5})\s+([^,]+)/)
|
||||
if match
|
||||
return match[2].strip
|
||||
end
|
||||
|
||||
# Fallback: extract last part after comma (assume it's city)
|
||||
parts = address.split(",")
|
||||
if parts.length > 1
|
||||
return parts[parts.length - 1].strip
|
||||
end
|
||||
|
||||
# Another fallback: look for common French city indicators
|
||||
city_indicators = [ "Paris", "Lyon", "Marseille", "Toulouse", "Nice", "Nantes", "Strasbourg", "Montpellier", "Bordeaux", "Lille" ]
|
||||
for city in city_indicators
|
||||
if address.downcase.include?(city.downcase)
|
||||
return city
|
||||
end
|
||||
end
|
||||
|
||||
""
|
||||
end
|
||||
|
||||
# Get image URL prioritizing old image field if it exists
|
||||
def display_image_url
|
||||
# First check if old image field exists and has a value
|
||||
return self[:image] if self[:image].present?
|
||||
|
||||
# Fall back to attached image
|
||||
return nil unless image.attached?
|
||||
|
||||
# Return the URL for the attached image
|
||||
Rails.application.routes.url_helpers.rails_blob_url(image, only_path: true)
|
||||
end
|
||||
|
||||
# Get image variants for different display sizes
|
||||
def event_image_variant(size = :medium)
|
||||
# For old image field, return the URL directly
|
||||
return self[:image] if self[:image].present?
|
||||
|
||||
# For attached images, process variants
|
||||
return nil unless image.attached?
|
||||
|
||||
case size
|
||||
when :large
|
||||
image.variant(resize_to_limit: [ 1200, 630 ])
|
||||
when :medium
|
||||
image.variant(resize_to_limit: [ 800, 450 ])
|
||||
when :small
|
||||
image.variant(resize_to_limit: [ 400, 225 ])
|
||||
else
|
||||
# Fallback to URL-based image
|
||||
image_url.presence
|
||||
@@ -100,6 +181,11 @@ class Event < ApplicationRecord
|
||||
end
|
||||
end
|
||||
|
||||
# Check if event has any image (old field or attached)
|
||||
def has_image?
|
||||
self[:image].present? || image.attached?
|
||||
end
|
||||
|
||||
# Check if coordinates were successfully geocoded or are fallback coordinates
|
||||
def geocoding_successful?
|
||||
coordinates_look_valid?
|
||||
@@ -203,6 +289,19 @@ class Event < ApplicationRecord
|
||||
|
||||
private
|
||||
|
||||
# Check if image is attached for the callback
|
||||
def image_attached?
|
||||
image.attached?
|
||||
end
|
||||
|
||||
# Handle image replacement when a new image is uploaded
|
||||
def handle_image_replacement
|
||||
# Clear the old image field if a new image is being attached
|
||||
if image.attached?
|
||||
self[:image] = nil
|
||||
end
|
||||
end
|
||||
|
||||
# Determine if we should perform server-side geocoding
|
||||
def should_geocode_address?
|
||||
# Don't geocode if address is blank
|
||||
|
||||
Reference in New Issue
Block a user