Skip to content

Commit f8b92eb

Browse files
mortbaueryksflip
andcommitted
feat: move document data from document plugin to active storage (#1050)
* 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: Philipp Rothmann <philipprothmann@posteo.de>
1 parent da1e191 commit f8b92eb

File tree

6 files changed

+124
-30
lines changed

6 files changed

+124
-30
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
class MoveDocumentsToActiveStorage < ActiveRecord::Migration[7.0]
2+
def up
3+
change_table :documents do |t|
4+
t.boolean :folder, default: false, null: false
5+
end
6+
7+
Document.find_each do |document|
8+
if document.data.present? && document.mime.present?
9+
document.attachment.attach(create_blob_from_document(document))
10+
else
11+
document.update(folder: true)
12+
end
13+
end
14+
15+
change_table :documents, bulk: true do |t|
16+
t.remove :data
17+
t.remove :mime
18+
end
19+
end
20+
21+
def down
22+
change_table :documents, bulk: true do |t|
23+
t.binary :data, limit: 16.megabyte
24+
t.string :mime
25+
t.remove :folder
26+
end
27+
28+
Document.find_each do |document|
29+
next unless document.attachment.attached?
30+
31+
document.update(
32+
data: document.attachment.download,
33+
mime: document.attachment.blob.content_type
34+
)
35+
end
36+
end
37+
38+
def create_blob_from_document(document)
39+
ActiveStorage::Blob.create_and_upload!(
40+
io: StringIO.new(document.data),
41+
filename: document.name,
42+
content_type: document.mime
43+
)
44+
end
45+
end

db/schema.rb

+4-4
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
#
1111
# It's strongly recommended that you check this file into your version control system.
1212

13-
ActiveRecord::Schema[7.0].define(version: 2024_04_04_004950) do
13+
ActiveRecord::Schema[7.0].define(version: 2024_06_26_124329) do
1414
create_table "action_text_rich_texts", charset: "utf8mb4", collation: "utf8mb4_general_ci", force: :cascade do |t|
1515
t.string "name", null: false
1616
t.text "body", size: :long
@@ -85,6 +85,7 @@
8585
t.datetime "deleted_at", precision: nil
8686
t.string "type"
8787
t.integer "quantity", default: 0
88+
t.integer "max_quantity"
8889
t.index ["article_category_id"], name: "index_articles_on_article_category_id"
8990
t.index ["name", "supplier_id"], name: "index_articles_on_name_and_supplier_id"
9091
t.index ["supplier_id"], name: "index_articles_on_supplier_id"
@@ -101,7 +102,7 @@
101102
create_table "bank_accounts", id: :integer, charset: "utf8mb4", collation: "utf8mb4_general_ci", force: :cascade do |t|
102103
t.string "name", null: false
103104
t.string "iban"
104-
t.string "description"
105+
t.text "description"
105106
t.decimal "balance", precision: 12, scale: 2, default: "0.0", null: false
106107
t.datetime "last_import", precision: nil
107108
t.string "import_continuation_point"
@@ -131,12 +132,11 @@
131132

132133
create_table "documents", id: :integer, charset: "utf8mb4", collation: "utf8mb4_general_ci", force: :cascade do |t|
133134
t.string "name"
134-
t.string "mime"
135-
t.binary "data", size: :long
136135
t.integer "created_by_user_id"
137136
t.datetime "created_at", precision: nil
138137
t.datetime "updated_at", precision: nil
139138
t.integer "parent_id"
139+
t.boolean "folder", default: false, null: false
140140
t.index ["parent_id"], name: "index_documents_on_parent_id"
141141
end
142142

plugins/documents/app/controllers/documents_controller.rb

+11-23
Original file line numberDiff line numberDiff line change
@@ -6,38 +6,33 @@ class DocumentsController < ApplicationController
66
def index
77
sort = if params['sort']
88
case params['sort']
9-
when 'name' then 'data IS NULL DESC, name'
9+
when 'name' then 'folder DESC, name'
1010
when 'created_at' then 'created_at'
11-
when 'name_reverse' then 'data IS NULL, name DESC'
11+
when 'name_reverse' then 'folder, name DESC'
1212
when 'created_at_reverse' then 'created_at DESC'
1313
end
1414
else
15-
'data IS NULL DESC, name'
15+
'folder DESC, name'
1616
end
1717
sort = Arel.sql(sort) # this is okay as we don't use user params directly
1818
@documents = Document.where(parent: @document).page(params[:page]).per(@per_page).order(sort)
1919
end
2020

2121
def new
2222
@document = Document.new parent_id: params[:document_id]
23-
@document.mime = '' unless params[:type] == 'folder'
23+
@document.folder = params[:type] == 'folder'
2424
end
2525

2626
def create
2727
@document = Document.new name: params[:document][:name]
2828
@document.parent = Document.find_by_id(params[:document][:parent_id])
29-
data = params[:document][:data]
30-
if data
31-
@document.data = data.read
32-
@document.mime = FileMagic.new(FileMagic::MAGIC_MIME).buffer(@document.data)
33-
raise t('.not_allowed_mime', mime: @document.mime) unless allowed_mime? @document.mime
34-
35-
if @document.name.empty?
36-
name = File.basename(data.original_filename)
37-
@document.name = name.gsub(/[^\w.-]/, '_')
38-
end
29+
@document.attachment = params[:document][:attachment]
30+
if !@document.attachment.nil? and @document.name.empty?
31+
name = File.basename(@document.attachment.filename.to_s)
32+
@document.name = name.gsub(/[^\w.-]/, '_')
3933
end
4034
@document.created_by = current_user
35+
@document.folder = !params[:document].key?(:attachment)
4136
@document.save!
4237
redirect_to @document.parent || documents_path, notice: t('.notice')
4338
rescue StandardError => e
@@ -55,6 +50,7 @@ def update
5550
def destroy
5651
@document = Document.find(params[:id])
5752
if @document.created_by == current_user or current_user.role_admin?
53+
@document.delete_attachment
5854
@document.destroy
5955
redirect_to documents_path, notice: t('.notice')
6056
else
@@ -67,7 +63,7 @@ def destroy
6763
def show
6864
@document = Document.find(params[:id])
6965
if @document.file?
70-
send_data(@document.data, filename: @document.filename, type: @document.mime)
66+
send_data(@document.attachment.download, filename: @document.name, type: @document.attachment.blob.content_type)
7167
else
7268
index
7369
render :index
@@ -77,12 +73,4 @@ def show
7773
def move
7874
@document = Document.find(params[:document_id])
7975
end
80-
81-
def allowed_mime?(mime)
82-
whitelist = FoodsoftConfig[:documents_allowed_extension].split
83-
MIME::Types.type_for(whitelist).each do |type|
84-
return true if type.like? mime
85-
end
86-
false
87-
end
8876
end

plugins/documents/app/models/document.rb

+18-2
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,18 @@ class Document < ApplicationRecord
44

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

7+
has_one_attached :attachment
8+
79
acts_as_tree
810

11+
validate :valid_attachment
12+
913
def file?
1014
!folder?
1115
end
1216

13-
def folder?
14-
mime.nil?
17+
def valid_attachment
18+
errors.add(:attachment, I18n.t('documents.create.not_allowed_mime', mime: attachment.content_type)) unless !attachment.attached? || allowed_mime?(attachment.content_type)
1519
end
1620

1721
def filename
@@ -27,4 +31,16 @@ def filename
2731

2832
"#{name}.#{types.first.preferred_extension}"
2933
end
34+
35+
def allowed_mime?(mime)
36+
whitelist = FoodsoftConfig[:documents_allowed_extension].split
37+
MIME::Types.type_for(whitelist).each do |type|
38+
return true if type.like? mime
39+
end
40+
false
41+
end
42+
43+
def delete_attachment
44+
attachment.purge_later
45+
end
3046
end

plugins/documents/app/views/documents/_form.html.haml

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
.modal-body
77
= f.input :name, as: :string, required: @document.folder?
88
- if @document.file?
9-
= f.input :data, as: :file, required: true
9+
= f.input :attachment, as: :file, input_html: {multiple: false}, direct_upload: true, required: true
1010
.modal-footer
1111
= link_to t('ui.close'), '#', class: 'btn', data: {dismiss: 'modal'}
1212
= f.submit t('.submit'), class: 'btn btn-primary'
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
class MoveDocumentsToActiveStorage < ActiveRecord::Migration[7.0]
2+
def up
3+
change_table :documents do |t|
4+
t.boolean :folder, default: false, null: false
5+
end
6+
7+
Document.find_each do |document|
8+
if document.data.present? && document.mime.present?
9+
document.attachment.attach(create_blob_from_document(document))
10+
else
11+
document.update(folder: true)
12+
end
13+
end
14+
15+
change_table :documents, bulk: true do |t|
16+
t.remove :data
17+
t.remove :mime
18+
end
19+
end
20+
21+
def down
22+
change_table :documents, bulk: true do |t|
23+
t.binary :data, limit: 16.megabyte
24+
t.string :mime
25+
t.remove :folder
26+
end
27+
28+
Document.find_each do |document|
29+
next unless document.attachment.attached?
30+
31+
document.update(
32+
data: document.attachment.download,
33+
mime: document.attachment.blob.content_type
34+
)
35+
end
36+
end
37+
38+
def create_blob_from_document(document)
39+
ActiveStorage::Blob.create_and_upload!(
40+
io: StringIO.new(document.data),
41+
filename: document.name,
42+
content_type: document.mime
43+
)
44+
end
45+
end

0 commit comments

Comments
 (0)