Fix Missing Restaurant Image
Purpose
This script repairs missing restaurant logos and gallery images by fetching production API data. If image data is missing, it uses fallback dummy assets.
Prerequisites
- Rails environment with production access
- Gems:
retriable,faraday - Run in controlled environment (helper pod or maintenance shell)
How to run
rails c --production
# paste and run script
Verification
- Check updated restaurants in admin UI.
- Confirm no broken image placeholders.
- Verify cache refresh workers completed successfully.
Rollback guidance
- Re-run using known-good source URLs.
- Restore from backup/snapshot if a bulk update is incorrect.
Script
# Fetch production data and fix missing logo/pictures.
host = 'https://hungryhub.com'
def fix_image_url(url)
return url if url.include?('http')
URI.join('https://images.hungryhub.com', URI.escape(url)).to_s
end
errors = []
dummy_logo_url = 'https://images.hungryhub.com/uploads/restaurant/logo/997/12764618_993228954095365_7698085734652638054_o.jpg'
dummy_picture_urls = [
'uploads/restaurants/997/photos/32963/RackMultipart20200220-229-13mf4s0.jpg',
'uploads/restaurants/997/photos/32964/RackMultipart20200220-229-fsfiie.jpg'
]
Restaurant.active.not_expired.find_each do |restaurant|
data = nil
if restaurant.logo.blank? || (restaurant.logo.present? && !restaurant.logo.file.present?)
data = Retriable.retriable do
response = Faraday.get("#{host}/api/v5/restaurants/#{restaurant.id}.json?include_packages=false&include_pictures=true&minor_version=3&preview_mode=false")
JSON.parse(response.body)
end
attributes = data['data']['attributes']
logo_url = attributes['logo_url']['medium']
restaurant.remote_logo_url = fix_image_url(logo_url.presence || dummy_logo_url)
restaurant.save!
end
data ||= Retriable.retriable do
response = Faraday.get("#{host}/api/v5/restaurants/#{restaurant.id}.json?include_packages=false&include_pictures=true&minor_version=3&preview_mode=false")
JSON.parse(response.body)
end
pictures = data['included'].select { |r| r['type'] == 'restaurants-pictures' }
restaurant.pictures.each_with_index do |picture, index|
if picture.item.blank? || (picture.item.present? && !picture.item.file.present?)
prod_picture = pictures[index]
picture.remote_item_url = fix_image_url(prod_picture&.dig('attributes', 'item', 'url') || dummy_picture_urls.sample)
picture.save!
end
end
if restaurant.pictures.cover.blank?
picture = restaurant.pictures.first
if picture
picture.tag_list << 'cover'
picture.save!
end
end
# Trigger compact data rebuild and cache refresh.
GenerateCompactRestaurantsWorker.perform_async(restaurant.id)
restaurant.refresh_view_cache_key
restaurant.touch
puts "done restaurant id -> #{restaurant.id}"
rescue StandardError => e
errors << { restaurant_id: restaurant.id, error: e.message }
end
puts "Failed restaurants: #{errors.map { |x| x[:restaurant_id] }.join(', ')}"