107 lines
3.0 KiB
Ruby
107 lines
3.0 KiB
Ruby
require "open-uri"
|
|
# A set of image URLs (thumbs) + Associated meta data.
|
|
class Image < ApplicationRecord
|
|
belongs_to :device
|
|
validates :device, presence: true
|
|
serialize :meta
|
|
|
|
# http://stackoverflow.com/a/5127684/1064917
|
|
after_initialize :set_defaults
|
|
|
|
def set_defaults
|
|
self.meta ||= {}
|
|
end
|
|
|
|
PLACEHOLDER = "/placeholder_farmbot.jpg\?text=Processing..."
|
|
PROTO = ENV["FORCE_SSL"] ? "https:" : "http:"
|
|
DEFAULT_URL = "#{PROTO}#{$API_URL}#{PLACEHOLDER}"
|
|
RMAGICK_STYLES = {
|
|
x1280: "1280x1280>",
|
|
x640: "640x640>",
|
|
x320: "320x320>",
|
|
x160: "160x160>",
|
|
x80: "80x80>",
|
|
}
|
|
MAX_IMAGE_SIZE = 7.megabytes
|
|
CONFIG = { default_url: DEFAULT_URL,
|
|
styles: RMAGICK_STYLES,
|
|
size: { in: 0..MAX_IMAGE_SIZE } }
|
|
BUCKET = ENV["GCS_BUCKET"]
|
|
|
|
ROOT_PATH = BUCKET ?
|
|
"https://#{BUCKET}.storage.googleapis.com" : "/system"
|
|
IMAGE_URL_TPL =
|
|
ROOT_PATH + "/images/attachments/%{chunks}/%{size}/%{filename}?%{timestamp}"
|
|
|
|
CONTENT_TYPES = ["image/jpg", "image/jpeg", "image/png", "image/gif"]
|
|
GCS_ACCESS_KEY_ID = ENV.fetch("GCS_KEY") { puts "Not using Google Cloud" }
|
|
GCS_HOST = "http://#{BUCKET}.storage.googleapis.com"
|
|
GCS_SECRET_ACCESS_KEY = ENV.fetch("GCS_ID") { puts "Not using Google Cloud" }
|
|
# Worst case scenario for 1280x1280 BMP.
|
|
GCS_BUCKET_NAME = ENV["GCS_BUCKET"]
|
|
|
|
has_one_attached :attachment
|
|
|
|
def set_attachment_by_url(url)
|
|
attachment.attach(io: URI.open(url), filename: "image_#{self.id}")
|
|
self.attachment_processed_at = Time.now
|
|
self
|
|
end
|
|
|
|
# Scenario:
|
|
# User clicks "take photo" and "delete" on Image#123 very quickly.
|
|
# Problem:
|
|
# Now there's a Delayed::Job pointing to (nonexistent) Image#123,
|
|
# causing runtime errors in the work queue.
|
|
# Solution:
|
|
# Don't retry failed deletions. Users can always click the "delete"
|
|
# button again if need be.
|
|
def self.maybe_destroy(id)
|
|
image = find_by(id: id)
|
|
image.destroy! if image
|
|
end
|
|
|
|
def legacy_image?
|
|
!!self.attachment_file_size # This is a now-unused legacy field.
|
|
end
|
|
|
|
def regular_image?
|
|
attachment && attachment.attached?
|
|
end
|
|
|
|
def regular_url
|
|
if BUCKET
|
|
# Not sure why. TODO: Investigate why Rails URL helpers don't work here.
|
|
"https://storage.googleapis.com/#{BUCKET}/#{attachment.key}"
|
|
else
|
|
Rails
|
|
.application
|
|
.routes
|
|
.url_helpers
|
|
.rails_blob_url(attachment)
|
|
end
|
|
end
|
|
|
|
def legacy_url(size)
|
|
url = IMAGE_URL_TPL % {
|
|
chunks: id.to_s.rjust(9, "0").scan(/.{3}/).join("/"),
|
|
filename: attachment_file_name,
|
|
size: size,
|
|
timestamp: attachment_updated_at.to_i,
|
|
}
|
|
return ENV["GCS_KEY"].present? ? url.gsub("http://", "https://") : url
|
|
end
|
|
|
|
def attachment_url(size = "x640")
|
|
# Detect legacy attachments by way of
|
|
# superceded PaperClip-related field.
|
|
# If it has an `attachment_file_size`,
|
|
# it was made with paperclip.
|
|
return regular_url if regular_image?
|
|
|
|
return legacy_url(size) if legacy_image?
|
|
|
|
return DEFAULT_URL
|
|
end
|
|
end
|