Rails Active Storage能否映射到数据库中预先存在的Images表



我正在开发一个遗留的Rails应用程序,该应用程序最近升级到Rails 5.2。它已经有了一个可以上传的roll your own Image实现,并且DB中已经有数百万个图像。Image模型belongs_to其他模型;它们中的每一个是CCD_ 3或CCD_。

这是图像表的模式:

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应用程序上没有安装)。

EDIT以上课程提出的一个问题(我没有写)是,我们建立的映像URL结构是否与Active Storage兼容。这个";url生成器";即使实际的源url信息被迁移到Blob中也能工作吗?可能我不了解AWS存储是如何工作的,也许没有真正的";源";url

我找到的所有教程和解释都讨论了在新的Rails应用程序上安装Active Storage,或者使用它向现有模型添加附件。这不是我的情况——我已经有了一个与十几个其他模型相关的Image模型,他们已经知道他们的";附件";即图像关系。

我的问题是,活动存储是否可以以某种方式利用现有的映像表及其关系,或者活动存储是否更恰当地被理解为无法与之集成的这种滚动自己设置的替代方案。

关于";Rails Active Storage without model";这似乎意味着可以在活动存储和模型之间进行映射。我不明白的是活动存储和现有映像模型之间的关系。据我所知,图像模型是has_one_attachedhas_many_attached(就像用户或产品会有附件一样)是没有意义的——它已经是附件本身的模型了。还是我搞错了?

ActiveStorage的核心实际上是三个表(和模型),它们在某种程度上与您的图像表相对应:

class CreateActiveStorageTables < ActiveRecord::Migration[5.2]
def change
# Use Active Record's configured type for primary and foreign keys
primary_key_type, foreign_key_type = primary_and_foreign_key_types
create_table :active_storage_blobs, id: primary_key_type do |t|
t.string   :key,          null: false
t.string   :filename,     null: false
t.string   :content_type
t.text     :metadata
t.string   :service_name, null: false
t.bigint   :byte_size,    null: false
t.string   :checksum,     null: false
if connection.supports_datetime_with_precision?
t.datetime :created_at, precision: 6, null: false
else
t.datetime :created_at, null: false
end
t.index [ :key ], unique: true
end
create_table :active_storage_attachments, id: primary_key_type do |t|
t.string     :name,     null: false
t.references :record,   null: false, polymorphic: true, index: false, type: foreign_key_type
t.references :blob,     null: false, type: foreign_key_type
if connection.supports_datetime_with_precision?
t.datetime :created_at, precision: 6, null: false
else
t.datetime :created_at, null: false
end
t.index [ :record_type, :record_id, :name, :blob_id ], name: "index_active_storage_attachments_uniqueness", unique: true
t.foreign_key :active_storage_blobs, column: :blob_id
end
create_table :active_storage_variant_records, id: primary_key_type do |t|
t.belongs_to :blob, null: false, index: false, type: foreign_key_type
t.string :variation_digest, null: false
t.index %i[ blob_id variation_digest ], name: "index_active_storage_variant_records_uniqueness", unique: true
t.foreign_key :active_storage_blobs, column: :blob_id
end
end
private
def primary_and_foreign_key_types
config = Rails.configuration.generators
setting = config.options[config.orm][:primary_key_type]
primary_key_type = setting || :primary_key
foreign_key_type = setting || :bigint
[primary_key_type, foreign_key_type]
end
end

正如您从迁移中看到的,它使用active_storage_blobs来存储有关所存储文件的实际信息。blob也可以有多种变体。

active_storage_attachments通过多态关联将Blob与资源(连接附件的模型)连接起来。这使您可以将has_one_attached/has_many_attached添加到应用程序中的任何模型中,而无需添加任何其他数据库列或表。

所以我正在考虑Active Storage(没有安装在这个Rails应用程序上)是否可以使用这个现有的设置。

让我们这样说吧-您不应该期望您可以将遗留数据插入ActiveStorage并播放。这是一款非常有主见的软件,主要围绕着能够以最低配置插入任何数量的型号的目标而设计。

ActiveStorage可能可以与现有设置协同工作(为新记录替换它),但用AS替换旧代码很可能需要大量的数据迁移,您还需要非常好地了解AS的工作原理。

我不明白的是活动存储和现有映像模型之间的关系。

这是因为实际上没有。ActiveSupport::AttachmentActiveSupport::Blob为Rails应用程序中具有附件的所有模型提供相同的角色。它的设计并没有考虑到对传统的支持。

相关内容