Handle CKEditor attachments with Active Storage

The code is based on what's generated using CKEditor's code generator.

We're doing one minor change to the `Ckeditor::Backend::ActiveStorage`
module; we're assigning the data in a `before_validation` instead of a
`before_save` callback. Validations with `file_validations` didn't work
otherwise; it looks like this backend was written with
`active_storage_validations` in mind [1].

Note we don't need to update the `name` column in the attachments table
because, when using Active Storage, CKEditor uses both `data` (as
attribute accessor) and `storage_data` (as attachment attribute).

[1] https://github.com/galetahub/ckeditor/blob/f9e48420ccb6dc/lib/generators/ckeditor/templates/active_record/active_storage/ckeditor/picture.rb#L4
This commit is contained in:
Javi Martín
2021-07-28 00:25:02 +02:00
parent 600f5c35e9
commit 8c82ff290b
3 changed files with 15 additions and 32 deletions

View File

@@ -1,5 +1,4 @@
class Ckeditor::Asset < ApplicationRecord class Ckeditor::Asset < ApplicationRecord
include Ckeditor::Orm::ActiveRecord::AssetBase include Ckeditor::Orm::ActiveRecord::AssetBase
include Ckeditor::Backend::ActiveStorage include Ckeditor::Backend::ActiveStorage
include Ckeditor::Backend::Paperclip
end end

View File

@@ -1,24 +1,14 @@
class Ckeditor::Picture < Ckeditor::Asset class Ckeditor::Picture < Ckeditor::Asset
include HasAttachment attr_accessor :data
has_one_attached :storage_data
has_attachment :data, validates :storage_data, file_content_type: { allow: /^image\/.*/ }, file_size: { less_than: 2.megabytes }
url: "/ckeditor_assets/pictures/:id/:style_:basename.:extension",
path: ":rails_root/public/ckeditor_assets/pictures/:id/:style_:basename.:extension",
styles: { content: "800>", thumb: "118x100#" }
do_not_validate_attachment_file_type :data
validate :attachment_presence
validates :data, file_content_type: { allow: /^image\/.*/ }, file_size: { less_than: 2.megabytes }
def url_content def url_content
url(:content) rails_representation_url(storage_data.variant(resize: "800>").processed, only_path: true)
end end
private def url_thumb
rails_representation_url(storage_data.variant(resize: "118x100").processed, only_path: true)
def attachment_presence end
unless data.present?
errors.add(:data, I18n.t("errors.messages.blank"))
end
end
end end

View File

@@ -14,9 +14,9 @@ module Ckeditor
module ClassMethods module ClassMethods
def self.extended(base) def self.extended(base)
base.class_eval do base.class_eval do
before_save :apply_data before_validation :apply_data
validate do validate do
if data.nil? || storage_file.nil? if data.nil? || file.nil?
errors.add(:data, :not_data_present, message: "data must be present") errors.add(:data, :not_data_present, message: "data must be present")
end end
end end
@@ -46,25 +46,19 @@ module Ckeditor
protected protected
def storage_file def file
@storage_file ||= storage_data @file ||= storage_data
end end
def blob def blob
@blob ||= ::ActiveStorage::Blob.find(storage_file.attachment.blob_id) @blob ||= ::ActiveStorage::Blob.find(file.attachment.blob_id)
end end
def apply_data def apply_data
non_paperclip_data = if data.is_a?(::Paperclip::Attachment) if data.is_a?(Ckeditor::Http::QqFile)
file.instance_variable_get("@target") storage_data.attach(io: data, filename: data.original_filename)
else
data
end
if non_paperclip_data.is_a?(Ckeditor::Http::QqFile)
storage_data.attach(io: non_paperclip_data, filename: non_paperclip_data.original_filename)
else else
storage_data.attach(non_paperclip_data) storage_data.attach(data)
end end
self.data_file_name = storage_data.blob.filename self.data_file_name = storage_data.blob.filename