Skip to content

Commit

Permalink
feat: move document data from document plugin to active storage (#1050)
Browse files Browse the repository at this point in the history
* move document data from document plugin to active storage

* implement rubocoop recommendations

* add migration

* add migration to standard as documents plugin is enabled by default

---------

Co-authored-by: Martin Ortbauer <[email protected]>
  • Loading branch information
mortbauer authored Jul 4, 2024
1 parent da1e191 commit 5158cec
Show file tree
Hide file tree
Showing 6 changed files with 124 additions and 30 deletions.
45 changes: 45 additions & 0 deletions db/migrate/20240306141647_move_documents_to_active_storage.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
class MoveDocumentsToActiveStorage < ActiveRecord::Migration[7.0]
def up
change_table :documents do |t|
t.boolean :folder, default: false, null: false
end

Document.find_each do |document|
if document.data.present? && document.mime.present?
document.attachment.attach(create_blob_from_document(document))
else
document.update(folder: true)
end
end

change_table :documents, bulk: true do |t|
t.remove :data
t.remove :mime
end
end

def down
change_table :documents, bulk: true do |t|
t.binary :data, limit: 16.megabyte
t.string :mime
t.remove :folder
end

Document.find_each do |document|
next unless document.attachment.attached?

document.update(
data: document.attachment.download,
mime: document.attachment.blob.content_type
)
end
end

def create_blob_from_document(document)
ActiveStorage::Blob.create_and_upload!(
io: StringIO.new(document.data),
filename: document.name,
content_type: document.mime
)
end
end
8 changes: 4 additions & 4 deletions db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema[7.0].define(version: 2024_04_04_004950) do
ActiveRecord::Schema[7.0].define(version: 2024_06_26_124329) do
create_table "action_text_rich_texts", charset: "utf8mb4", collation: "utf8mb4_general_ci", force: :cascade do |t|
t.string "name", null: false
t.text "body", size: :long
Expand Down Expand Up @@ -85,6 +85,7 @@
t.datetime "deleted_at", precision: nil
t.string "type"
t.integer "quantity", default: 0
t.integer "max_quantity"
t.index ["article_category_id"], name: "index_articles_on_article_category_id"
t.index ["name", "supplier_id"], name: "index_articles_on_name_and_supplier_id"
t.index ["supplier_id"], name: "index_articles_on_supplier_id"
Expand All @@ -101,7 +102,7 @@
create_table "bank_accounts", id: :integer, charset: "utf8mb4", collation: "utf8mb4_general_ci", force: :cascade do |t|
t.string "name", null: false
t.string "iban"
t.string "description"
t.text "description"
t.decimal "balance", precision: 12, scale: 2, default: "0.0", null: false
t.datetime "last_import", precision: nil
t.string "import_continuation_point"
Expand Down Expand Up @@ -131,12 +132,11 @@

create_table "documents", id: :integer, charset: "utf8mb4", collation: "utf8mb4_general_ci", force: :cascade do |t|
t.string "name"
t.string "mime"
t.binary "data", size: :long
t.integer "created_by_user_id"
t.datetime "created_at", precision: nil
t.datetime "updated_at", precision: nil
t.integer "parent_id"
t.boolean "folder", default: false, null: false
t.index ["parent_id"], name: "index_documents_on_parent_id"
end

Expand Down
34 changes: 11 additions & 23 deletions plugins/documents/app/controllers/documents_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,38 +6,33 @@ class DocumentsController < ApplicationController
def index
sort = if params['sort']
case params['sort']
when 'name' then 'data IS NULL DESC, name'
when 'name' then 'folder DESC, name'
when 'created_at' then 'created_at'
when 'name_reverse' then 'data IS NULL, name DESC'
when 'name_reverse' then 'folder, name DESC'
when 'created_at_reverse' then 'created_at DESC'
end
else
'data IS NULL DESC, name'
'folder DESC, name'
end
sort = Arel.sql(sort) # this is okay as we don't use user params directly
@documents = Document.where(parent: @document).page(params[:page]).per(@per_page).order(sort)
end

def new
@document = Document.new parent_id: params[:document_id]
@document.mime = '' unless params[:type] == 'folder'
@document.folder = params[:type] == 'folder'
end

def create
@document = Document.new name: params[:document][:name]
@document.parent = Document.find_by_id(params[:document][:parent_id])
data = params[:document][:data]
if data
@document.data = data.read
@document.mime = FileMagic.new(FileMagic::MAGIC_MIME).buffer(@document.data)
raise t('.not_allowed_mime', mime: @document.mime) unless allowed_mime? @document.mime

if @document.name.empty?
name = File.basename(data.original_filename)
@document.name = name.gsub(/[^\w.-]/, '_')
end
@document.attachment = params[:document][:attachment]
if !@document.attachment.nil? and @document.name.empty?
name = File.basename(@document.attachment.filename.to_s)
@document.name = name.gsub(/[^\w.-]/, '_')
end
@document.created_by = current_user
@document.folder = !params[:document].key?(:attachment)
@document.save!
redirect_to @document.parent || documents_path, notice: t('.notice')
rescue StandardError => e
Expand All @@ -55,6 +50,7 @@ def update
def destroy
@document = Document.find(params[:id])
if @document.created_by == current_user or current_user.role_admin?
@document.delete_attachment
@document.destroy
redirect_to documents_path, notice: t('.notice')
else
Expand All @@ -67,7 +63,7 @@ def destroy
def show
@document = Document.find(params[:id])
if @document.file?
send_data(@document.data, filename: @document.filename, type: @document.mime)
send_data(@document.attachment.download, filename: @document.name, type: @document.attachment.blob.content_type)
else
index
render :index
Expand All @@ -77,12 +73,4 @@ def show
def move
@document = Document.find(params[:document_id])
end

def allowed_mime?(mime)
whitelist = FoodsoftConfig[:documents_allowed_extension].split
MIME::Types.type_for(whitelist).each do |type|
return true if type.like? mime
end
false
end
end
20 changes: 18 additions & 2 deletions plugins/documents/app/models/document.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,18 @@ class Document < ApplicationRecord

belongs_to :created_by, class_name: 'User', foreign_key: 'created_by_user_id'

has_one_attached :attachment

acts_as_tree

validate :valid_attachment

def file?
!folder?
end

def folder?
mime.nil?
def valid_attachment
errors.add(:attachment, I18n.t('documents.create.not_allowed_mime', mime: attachment.content_type)) unless !attachment.attached? || allowed_mime?(attachment.content_type)
end

def filename
Expand All @@ -27,4 +31,16 @@ def filename

"#{name}.#{types.first.preferred_extension}"
end

def allowed_mime?(mime)
whitelist = FoodsoftConfig[:documents_allowed_extension].split
MIME::Types.type_for(whitelist).each do |type|
return true if type.like? mime
end
false
end

def delete_attachment
attachment.purge_later
end
end
2 changes: 1 addition & 1 deletion plugins/documents/app/views/documents/_form.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
.modal-body
= f.input :name, as: :string, required: @document.folder?
- if @document.file?
= f.input :data, as: :file, required: true
= f.input :attachment, as: :file, input_html: {multiple: false}, direct_upload: true, required: true
.modal-footer
= link_to t('ui.close'), '#', class: 'btn', data: {dismiss: 'modal'}
= f.submit t('.submit'), class: 'btn btn-primary'
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
class MoveDocumentsToActiveStorage < ActiveRecord::Migration[7.0]
def up
change_table :documents do |t|
t.boolean :folder, default: false, null: false
end

Document.find_each do |document|
if document.data.present? && document.mime.present?
document.attachment.attach(create_blob_from_document(document))
else
document.update(folder: true)
end
end

change_table :documents, bulk: true do |t|
t.remove :data
t.remove :mime
end
end

def down
change_table :documents, bulk: true do |t|
t.binary :data, limit: 16.megabyte
t.string :mime
t.remove :folder
end

Document.find_each do |document|
next unless document.attachment.attached?

document.update(
data: document.attachment.download,
mime: document.attachment.blob.content_type
)
end
end

def create_blob_from_document(document)
ActiveStorage::Blob.create_and_upload!(
io: StringIO.new(document.data),
filename: document.name,
content_type: document.mime
)
end
end

0 comments on commit 5158cec

Please sign in to comment.