【发布时间】:2021-10-23 21:01:17
【问题描述】:
我正在开发一个旧版 Rails 应用程序,最近升级到 Rails 5.2。它已经有一个自己滚动的上传图片实现,并且数据库中已经有数百万张图片。 Image型号belongs_to其他型号;他们每个人要么has_many :images要么has_one :image。
这是 Image 表的架构:
create_table "images", id: :integer, unsigned: true, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t|
t.datetime "created_at"
t.datetime "updated_at"
t.string "content_type", limit: 100
t.integer "user_id"
t.date "when"
t.text "notes"
t.string "copyright_holder", limit: 100
t.integer "license_id", default: 1, null: false
t.integer "num_views", default: 0, null: false
t.datetime "last_view"
t.integer "width"
t.integer "height"
t.float "vote_cache"
t.boolean "ok_for_export", default: true, null: false
t.string "original_name", limit: 120, default: ""
t.boolean "transferred", default: false, null: false
t.boolean "gps_stripped", default: false, null: false
end
部分实现是Image、Image::Url 的子类,它根据请求的大小以及 ImageMagick 已经生成的各种大小获取图像的 URL(在 AWS 上)。
class Image
class Url
SUBDIRECTORIES = {
full_size: "orig",
huge: "1280",
large: "960",
medium: "640",
small: "320",
thumbnail: "thumb"
}.freeze
SUBDIRECTORY_TO_SIZE = {
"orig" => :full_size,
"1280" => :huge,
"960" => :large,
"640" => :medium,
"320" => :small,
"thumb" => :thumbnail
}.freeze
attr_accessor :size, :id, :transferred, :extension
def initialize(args)
size = args[:size]
size = SUBDIRECTORY_TO_SIZE[size] unless size.is_a?(Symbol)
size = :full_size if size == :original
self.size = size
self.id = args[:id]
self.transferred = args[:transferred]
self.extension = args[:extension]
end
def url
for source in source_order
return source_url(source) if source_exists?(source)
end
source_url(fallback_source)
end
def source_exists?(source)
spec = format_spec(source, :test)
case spec
when :transferred_flag
transferred
when /^file:/
local_file_exists?(spec)
when /^http:/
remote_file_exists?(spec)
when /^https:/
remote_file_exists?(spec)
else
raise("Invalid image source test spec for "\
"#{source.inspect}: #{spec.inspect}")
end
end
def local_file_exists?(spec)
File.exist?(file_name(spec)[7..])
end
def remote_file_exists?(spec)
url = URI.parse(file_name(spec))
result = Net::HTTP.new(url.host, url.port).request_head(url.path)
result.code == 200
end
def source_url(source)
file_name(format_spec(source, :read))
end
def file_name(path)
"#{path}/#{subdirectory}/#{id}.#{extension}"
end
def subdirectory
SUBDIRECTORIES[size] || raise("Invalid size: #{size.inspect}")
end
def source_order
OurApp.image_precedence[size] || OurApp.image_precedence[:default]
end
def fallback_source
OurApp.image_fallback_source
end
def format_spec(source, mode)
spec = specs(source)[mode]
spec.is_a?(String) ? format(spec, root: OurApp.root) : spec
end
def specs(source)
OurApp.image_sources[source] ||
raise("Missing image source: #{source.inspect}")
end
end
end
所以我正在考虑是否可以以某种方式迁移我们现有的数据表以使用 Active Storage(此 Rails 应用程序上未安装)。
编辑 上面的课程提出的一个问题,我没有写,是我们建立的图像 URL 结构是否与 Active Storage 兼容。即使将实际的源 url 信息迁移到 blob,这个“url 生成器”也会工作吗?可能我不了解 AWS 存储的工作原理,也许没有真正的“源”网址。
我发现的所有教程和解释器都讨论了在新的 Rails 应用程序上安装 Active Storage,或使用它向现有模型添加附件。那不是我的情况——我已经有一个与其他十几个模型相关的图像模型,并且他们已经知道他们的“附件”,即图像关系是什么。
我的问题是,Active Storage 能否以某种方式利用现有的 Image 表及其关系——或者更恰当地将 Active Storage 理解为这种自行滚动设置的替代方案,即无法与之集成。
There is an SO question 关于“Rails Active Storage without model”似乎暗示 Active Storage 和模型之间可以发生映射。我不明白 Active Storage 和现有 Image 模型之间的关系。据我了解,Image 模型将 has_one_attached 或 has_many_attached (因为用户或产品将具有附件)是没有意义的 - 它已经是附件本身的模型。还是我弄错了?
【问题讨论】:
标签: ruby-on-rails rails-activestorage