Rails Active Storage 可以映射到数据库中预先存在的图像 table 吗?
Can Rails Active Storage map to a pre-existing Images table in the database?
我正在开发旧版 Rails 应用程序,最近升级到 Rails 5.2。它已经有一个带有上传功能的自定义图像实现,并且数据库中已经有数百万张图像。 Image
型号belongs_to
其他型号;他们每个人要么 has_many :images
要么 has_one :image
.
这是图片的架构 table:
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
的子 class,它根据大小获取图像的 URL(在 AWS 上)请求,ImageMagick 已经生成的各种尺寸。
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
所以我正在考虑我们现有的数据 table 是否可以以某种方式迁移以与 Active Storage(未安装在此 Rails 应用程序上)一起使用。
EDIT 上面class提出的一个问题,我没写,是不是我们建立的图像URL结构将与 Active Storage 兼容。即使实际源 url 信息已迁移到 blob,此“url 生成器”是否仍能正常工作?可能我不了解 AWS 存储的工作原理,也许没有真正的“来源”url.
我找到的所有教程和解释器都讨论了在新的 Rails 应用程序上安装 Active Storage,或使用它向现有模型添加附件。那不是我的情况——我已经有一个与其他十几个模型相关的图像模型,并且他们已经知道他们的“附件”,即图像关系,是什么。
我的问题是,Active Storage 能否以某种方式利用现有图像 table 及其关系——或者 Active Storage 是否更恰当地理解为这个自己动手的设置,无法与之集成。
关于“Rails 没有模型的 Active Storage”,这似乎暗示 Active Storage 和模型之间的映射可以发生。我不明白的是 Active Storage 和现有图像模型之间的关系。据我所知,图像模型 has_one_attached
或 has_many_attached
(因为用户或产品会有附件)是没有意义的 - 它已经是附件本身的模型。还是我理解错了?
ActiveStorage 的核心实际上是三个 table(和模型),它们在某种程度上对应于您的图像 table:
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
添加到应用程序中的任何模型,而无需添加任何其他数据库列或 table。
So I'm considering whether Active Storage (which is not installed on this Rails app) could work with this existing setup.
让我们这样说吧——您不应该期望您可以将遗留数据即插即用到 ActiveStorage 中。它是一款非常有主见的软件,主要围绕能够以最少的配置插入任意数量的模型这一目标而设计。
ActiveStorage 可能与您现有的设置协同工作(将其替换为新记录),但是用 AS 替换遗留代码很可能需要一些繁重的数据迁移,您还需要很好地理解如何AS 作品。
What i don't understand is the relationship betwen Active Storage and an existing Image model.
那是因为真的有 none。 ActiveSupport::Attachment
和 ActiveSupport::Blob
对您的 Rails 应用程序中具有附件的所有模型起到相同的作用。它在设计时并未考虑到遗留支持。
我正在开发旧版 Rails 应用程序,最近升级到 Rails 5.2。它已经有一个带有上传功能的自定义图像实现,并且数据库中已经有数百万张图像。 Image
型号belongs_to
其他型号;他们每个人要么 has_many :images
要么 has_one :image
.
这是图片的架构 table:
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
的子 class,它根据大小获取图像的 URL(在 AWS 上)请求,ImageMagick 已经生成的各种尺寸。
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
所以我正在考虑我们现有的数据 table 是否可以以某种方式迁移以与 Active Storage(未安装在此 Rails 应用程序上)一起使用。
EDIT 上面class提出的一个问题,我没写,是不是我们建立的图像URL结构将与 Active Storage 兼容。即使实际源 url 信息已迁移到 blob,此“url 生成器”是否仍能正常工作?可能我不了解 AWS 存储的工作原理,也许没有真正的“来源”url.
我找到的所有教程和解释器都讨论了在新的 Rails 应用程序上安装 Active Storage,或使用它向现有模型添加附件。那不是我的情况——我已经有一个与其他十几个模型相关的图像模型,并且他们已经知道他们的“附件”,即图像关系,是什么。
我的问题是,Active Storage 能否以某种方式利用现有图像 table 及其关系——或者 Active Storage 是否更恰当地理解为这个自己动手的设置,无法与之集成。
has_one_attached
或 has_many_attached
(因为用户或产品会有附件)是没有意义的 - 它已经是附件本身的模型。还是我理解错了?
ActiveStorage 的核心实际上是三个 table(和模型),它们在某种程度上对应于您的图像 table:
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
添加到应用程序中的任何模型,而无需添加任何其他数据库列或 table。
So I'm considering whether Active Storage (which is not installed on this Rails app) could work with this existing setup.
让我们这样说吧——您不应该期望您可以将遗留数据即插即用到 ActiveStorage 中。它是一款非常有主见的软件,主要围绕能够以最少的配置插入任意数量的模型这一目标而设计。
ActiveStorage 可能与您现有的设置协同工作(将其替换为新记录),但是用 AS 替换遗留代码很可能需要一些繁重的数据迁移,您还需要很好地理解如何AS 作品。
What i don't understand is the relationship betwen Active Storage and an existing Image model.
那是因为真的有 none。 ActiveSupport::Attachment
和 ActiveSupport::Blob
对您的 Rails 应用程序中具有附件的所有模型起到相同的作用。它在设计时并未考虑到遗留支持。