active_storage_db 1.4.0 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +13 -14
- data/Rakefile +1 -2
- data/app/controllers/active_storage_db/files_controller.rb +6 -5
- data/app/models/active_storage_db/file.rb +1 -1
- data/db/migrate/20200702202022_create_active_storage_db_files.rb +1 -2
- data/lib/active_storage/service/db_service.rb +70 -32
- data/lib/active_storage/service/db_service_rails70.rb +6 -3
- data/lib/active_storage_db/engine.rb +8 -0
- data/lib/active_storage_db/version.rb +1 -1
- data/lib/tasks/active_storage_db_tasks.rake +35 -16
- metadata +3 -34
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ef4de196ae1110b81dfa6adfdd641e82bd009d3d1ed7fd0fbdd497d66cee089f
|
|
4
|
+
data.tar.gz: f02ae2f4d33d4f054814b0c1fa178af09ec2f6084beb02448af43cf16b45db40
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 331e0ccf899fba5d8ed88eacfd95612b074fb403696092b0744a81641dcea1d83f7c723dd430281e3a91224a01657f132ce5cdf9eb06fc04b4e9b6ac98ba6c5d
|
|
7
|
+
data.tar.gz: 4e657d03432899f4c18bac98201c639c0473150fedd0f83bbfe1ae674000e3765aca3111d823aaf46178a9e4195c44c9ca28297256b1e573bcbe3747cda16f72
|
data/README.md
CHANGED
|
@@ -5,15 +5,13 @@
|
|
|
5
5
|
[](https://codeclimate.com/github/blocknotes/active_storage_db/maintainability)
|
|
6
6
|
|
|
7
7
|
[](https://github.com/blocknotes/active_storage_db/actions/workflows/linters.yml)
|
|
8
|
-
[](https://github.com/blocknotes/active_storage_db/actions/workflows/specs_postgres_rails81.yml)
|
|
9
|
+
[](https://github.com/blocknotes/active_storage_db/actions/workflows/specs_mysql_rails81.yml)
|
|
10
10
|
|
|
11
|
-
An Active Storage service upload/download plugin that stores files in a PostgreSQL or MySQL database.
|
|
11
|
+
An Active Storage service upload/download plugin that stores files in a PostgreSQL or MySQL database.
|
|
12
|
+
Experimental support also for MSSQL and SQLite.
|
|
12
13
|
|
|
13
|
-
|
|
14
|
-
- attachment data stored in a binary field (or blob);
|
|
15
|
-
- all service methods implemented;
|
|
16
|
-
- supports Rails _6_ and _7_.
|
|
14
|
+
Attachment data get stored in a binary field (or blob).
|
|
17
15
|
|
|
18
16
|
Useful also with platforms like Heroku (due to their ephemeral file system).
|
|
19
17
|
|
|
@@ -23,8 +21,8 @@ Useful also with platforms like Heroku (due to their ephemeral file system).
|
|
|
23
21
|
- Add to your Gemfile `gem 'active_storage_db'` (and execute: `bundle`)
|
|
24
22
|
- Install the gem migrations: `bin/rails active_storage_db:install:migrations` (and execute: `bin/rails db:migrate`)
|
|
25
23
|
- Add to your `config/routes.rb`: `mount ActiveStorageDB::Engine => '/active_storage_db'`
|
|
26
|
-
- Change Active Storage service in
|
|
27
|
-
- Add to
|
|
24
|
+
- Change Active Storage service in _config/environments/development.rb_ to: `config.active_storage.service = :db`
|
|
25
|
+
- Add to _config/storage.yml_:
|
|
28
26
|
|
|
29
27
|
```yml
|
|
30
28
|
db:
|
|
@@ -69,17 +67,18 @@ bin/rails 'asdb:search[some_filename]'
|
|
|
69
67
|
bin/rails 'asdb:download[123,/tmp]'
|
|
70
68
|
```
|
|
71
69
|
|
|
70
|
+
## Development
|
|
71
|
+
|
|
72
|
+
Project created by [Mattia Roccoberton](http://blocknot.es), thanks also to the good guys that opened issues and pull requests from time to time.
|
|
73
|
+
|
|
74
|
+
For development information please check [this document](extra/development.md).
|
|
75
|
+
|
|
72
76
|
## Do you like it? Star it!
|
|
73
77
|
|
|
74
78
|
If you use this component just star it. A developer is more motivated to improve a project when there is some interest.
|
|
75
79
|
|
|
76
80
|
Or consider offering me a coffee, it's a small thing but it is greatly appreciated: [about me](https://www.blocknot.es/about-me).
|
|
77
81
|
|
|
78
|
-
## Development
|
|
79
|
-
|
|
80
|
-
- Author: [Mattia Roccoberton](https://blocknot.es/)
|
|
81
|
-
- Inspired by [activestorage-database-service](https://github.com/TitovDigital/activestorage-database-service) project
|
|
82
|
-
|
|
83
82
|
## License
|
|
84
83
|
|
|
85
84
|
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
CHANGED
|
@@ -16,8 +16,7 @@ RDoc::Task.new(:rdoc) do |rdoc|
|
|
|
16
16
|
rdoc.rdoc_files.include('lib/**/*.rb')
|
|
17
17
|
end
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
APP_RAKEFILE = File.expand_path("spec/dummy#{app_ver}/Rakefile", __dir__)
|
|
19
|
+
APP_RAKEFILE = File.expand_path("spec/dummy/Rakefile", __dir__)
|
|
21
20
|
load 'rails/tasks/engine.rake'
|
|
22
21
|
|
|
23
22
|
load 'rails/tasks/statistics.rake'
|
|
@@ -16,19 +16,20 @@ module ActiveStorageDB
|
|
|
16
16
|
|
|
17
17
|
def update
|
|
18
18
|
if (token = decode_verified_token)
|
|
19
|
-
file_uploaded = upload_file(token
|
|
20
|
-
head(file_uploaded ? :no_content :
|
|
19
|
+
file_uploaded = upload_file(token)
|
|
20
|
+
head(file_uploaded ? :no_content : ActiveStorageDB::UNPROCESSABLE_STATUS)
|
|
21
21
|
else
|
|
22
22
|
head(:not_found)
|
|
23
23
|
end
|
|
24
24
|
rescue ActiveStorage::IntegrityError
|
|
25
|
-
head(
|
|
25
|
+
head(ActiveStorageDB::UNPROCESSABLE_STATUS)
|
|
26
26
|
end
|
|
27
27
|
|
|
28
28
|
private
|
|
29
29
|
|
|
30
30
|
def acceptable_content?(token)
|
|
31
|
-
token[:content_type] == request.
|
|
31
|
+
token[:content_type] == request.media_type &&
|
|
32
|
+
token[:content_length] == request.content_length
|
|
32
33
|
end
|
|
33
34
|
|
|
34
35
|
def db_service
|
|
@@ -53,7 +54,7 @@ module ActiveStorageDB
|
|
|
53
54
|
send_data(db_service.download(key), options)
|
|
54
55
|
end
|
|
55
56
|
|
|
56
|
-
def upload_file(token
|
|
57
|
+
def upload_file(token) # rubocop:disable Naming/PredicateMethod
|
|
57
58
|
return false unless acceptable_content?(token)
|
|
58
59
|
|
|
59
60
|
db_service.upload(token[:key], request.body, checksum: token[:checksum])
|
|
@@ -20,7 +20,6 @@ class CreateActiveStorageDBFiles < ActiveRecord::Migration[6.0]
|
|
|
20
20
|
|
|
21
21
|
def primary_key_type
|
|
22
22
|
config = Rails.configuration.generators
|
|
23
|
-
|
|
24
|
-
primary_key_type || :primary_key
|
|
23
|
+
config.options.dig(config.orm, :primary_key_type) || :primary_key
|
|
25
24
|
end
|
|
26
25
|
end
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
4
|
-
require
|
|
5
|
-
require
|
|
3
|
+
require "active_storage/service/db_service_rails60"
|
|
4
|
+
require "active_storage/service/db_service_rails61"
|
|
5
|
+
require "active_storage/service/db_service_rails70"
|
|
6
6
|
|
|
7
7
|
module ActiveStorage
|
|
8
8
|
# Wraps a DB table as an Active Storage service. See ActiveStorage::Service
|
|
@@ -18,16 +18,26 @@ module ActiveStorage
|
|
|
18
18
|
end
|
|
19
19
|
# :nocov:
|
|
20
20
|
|
|
21
|
+
MINIMUM_CHUNK_SIZE = 1
|
|
22
|
+
|
|
21
23
|
def initialize(public: false, **)
|
|
22
|
-
@chunk_size = ENV.fetch(
|
|
24
|
+
@chunk_size = [ENV.fetch("ASDB_CHUNK_SIZE") { 1.megabytes }.to_i, MINIMUM_CHUNK_SIZE].max
|
|
25
|
+
@max_size = ENV.fetch("ASDB_MAX_FILE_SIZE", nil)&.to_i
|
|
23
26
|
@public = public
|
|
24
27
|
end
|
|
25
28
|
|
|
26
29
|
def upload(key, io, checksum: nil, **)
|
|
27
30
|
instrument :upload, key: key, checksum: checksum do
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
+
data = io.read
|
|
32
|
+
if @max_size && data.bytesize > @max_size
|
|
33
|
+
raise ArgumentError, "File size exceeds the maximum allowed size of #{@max_size} bytes"
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
if checksum
|
|
37
|
+
digest = Digest::MD5.base64digest(data)
|
|
38
|
+
raise ActiveStorage::IntegrityError unless digest == checksum
|
|
39
|
+
end
|
|
40
|
+
::ActiveStorageDB::File.create!(ref: key, data: data)
|
|
31
41
|
end
|
|
32
42
|
end
|
|
33
43
|
|
|
@@ -45,11 +55,13 @@ module ActiveStorage
|
|
|
45
55
|
|
|
46
56
|
def download_chunk(key, range)
|
|
47
57
|
instrument :download_chunk, key: key, range: range do
|
|
58
|
+
# NOTE: from/size are derived from Range#begin and Range#size (always integers),
|
|
59
|
+
# so string interpolation into SQL is safe here.
|
|
48
60
|
from = range.begin + 1
|
|
49
61
|
size = range.size
|
|
50
62
|
args = adapter_sqlserver? || adapter_sqlite? ? "data, #{from}, #{size}" : "data FROM #{from} FOR #{size}"
|
|
51
63
|
record = object_for(key, fields: "SUBSTRING(#{args}) AS chunk")
|
|
52
|
-
raise
|
|
64
|
+
raise ActiveStorage::FileNotFoundError unless record
|
|
53
65
|
|
|
54
66
|
record.chunk
|
|
55
67
|
end
|
|
@@ -57,22 +69,28 @@ module ActiveStorage
|
|
|
57
69
|
|
|
58
70
|
def delete(key)
|
|
59
71
|
instrument :delete, key: key do
|
|
60
|
-
|
|
61
|
-
|
|
72
|
+
comment = "DBService#delete"
|
|
73
|
+
record = ::ActiveStorageDB::File.annotate(comment).find_by(ref: key)
|
|
74
|
+
record&.destroy
|
|
75
|
+
# NOTE: Ignore files already deleted
|
|
76
|
+
!record.nil?
|
|
62
77
|
end
|
|
63
78
|
end
|
|
64
79
|
|
|
65
80
|
def delete_prefixed(prefix)
|
|
66
81
|
instrument :delete_prefixed, prefix: prefix do
|
|
67
|
-
|
|
82
|
+
comment = "DBService#delete_prefixed"
|
|
83
|
+
sanitized_prefix = "#{ActiveRecord::Base.sanitize_sql_like(prefix)}%"
|
|
84
|
+
::ActiveStorageDB::File.annotate(comment).where("ref LIKE ?", sanitized_prefix).destroy_all
|
|
68
85
|
end
|
|
69
86
|
end
|
|
70
87
|
|
|
71
88
|
def exist?(key)
|
|
72
89
|
instrument :exist, key: key do |payload|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
90
|
+
comment = "DBService#exist?"
|
|
91
|
+
result = ::ActiveStorageDB::File.annotate(comment).exists?(ref: key)
|
|
92
|
+
payload[:exist] = result
|
|
93
|
+
result
|
|
76
94
|
end
|
|
77
95
|
end
|
|
78
96
|
|
|
@@ -84,7 +102,7 @@ module ActiveStorage
|
|
|
84
102
|
content_type: content_type,
|
|
85
103
|
content_length: content_length,
|
|
86
104
|
checksum: checksum,
|
|
87
|
-
service_name:
|
|
105
|
+
service_name: service_name_for_token
|
|
88
106
|
},
|
|
89
107
|
expires_in: expires_in,
|
|
90
108
|
purpose: :blob_token
|
|
@@ -97,17 +115,33 @@ module ActiveStorage
|
|
|
97
115
|
end
|
|
98
116
|
|
|
99
117
|
def headers_for_direct_upload(_key, content_type:, **)
|
|
100
|
-
{
|
|
118
|
+
{ "Content-Type" => content_type }
|
|
101
119
|
end
|
|
102
120
|
|
|
103
121
|
private
|
|
104
122
|
|
|
123
|
+
def service_name_for_token
|
|
124
|
+
name.presence || "db"
|
|
125
|
+
end
|
|
126
|
+
|
|
105
127
|
def adapter_sqlite?
|
|
106
|
-
@adapter_sqlite
|
|
128
|
+
return @adapter_sqlite if defined?(@adapter_sqlite)
|
|
129
|
+
|
|
130
|
+
@adapter_sqlite = active_storage_db_adapter_name == "SQLite"
|
|
107
131
|
end
|
|
108
132
|
|
|
109
133
|
def adapter_sqlserver?
|
|
110
|
-
@adapter_sqlserver
|
|
134
|
+
return @adapter_sqlserver if defined?(@adapter_sqlserver)
|
|
135
|
+
|
|
136
|
+
@adapter_sqlserver = active_storage_db_adapter_name == "SQLServer"
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def active_storage_db_adapter_name
|
|
140
|
+
if ActiveStorageDB::File.respond_to?(:lease_connection)
|
|
141
|
+
ActiveStorageDB::File.lease_connection.adapter_name
|
|
142
|
+
else
|
|
143
|
+
ActiveStorageDB::File.connection.adapter_name
|
|
144
|
+
end
|
|
111
145
|
end
|
|
112
146
|
|
|
113
147
|
def generate_url(key, expires_in:, filename:, content_type:, disposition:)
|
|
@@ -117,7 +151,7 @@ module ActiveStorage
|
|
|
117
151
|
key: key,
|
|
118
152
|
disposition: content_disposition,
|
|
119
153
|
content_type: content_type,
|
|
120
|
-
service_name:
|
|
154
|
+
service_name: service_name_for_token
|
|
121
155
|
},
|
|
122
156
|
expires_in: expires_in,
|
|
123
157
|
purpose: :blob_key
|
|
@@ -135,34 +169,38 @@ module ActiveStorage
|
|
|
135
169
|
)
|
|
136
170
|
end
|
|
137
171
|
|
|
138
|
-
def ensure_integrity_of(key, checksum)
|
|
139
|
-
return if Digest::MD5.base64digest(object_for(key).data) == checksum
|
|
140
|
-
|
|
141
|
-
delete(key)
|
|
142
|
-
raise ActiveStorage::IntegrityError
|
|
143
|
-
end
|
|
144
|
-
|
|
145
172
|
def retrieve_file(key)
|
|
146
173
|
file = object_for(key)
|
|
147
|
-
raise
|
|
174
|
+
raise ActiveStorage::FileNotFoundError unless file
|
|
148
175
|
|
|
149
176
|
file.data
|
|
150
177
|
end
|
|
151
178
|
|
|
152
179
|
def object_for(key, fields: nil)
|
|
153
|
-
|
|
154
|
-
|
|
180
|
+
comment = "DBService#object_for"
|
|
181
|
+
scope = ::ActiveStorageDB::File.annotate(comment)
|
|
182
|
+
scope = scope.select(fields) if fields
|
|
183
|
+
scope.find_by(ref: key)
|
|
155
184
|
end
|
|
156
185
|
|
|
157
186
|
def stream(key)
|
|
158
|
-
|
|
159
|
-
size = object_for(key, fields: "#{data_size} AS size")&.size || raise(ActiveStorage::FileNotFoundError)
|
|
187
|
+
size = object_for(key, fields: data_size)&.size || raise(ActiveStorage::FileNotFoundError)
|
|
160
188
|
(size / @chunk_size.to_f).ceil.times.each do |i|
|
|
161
|
-
range = (i * @chunk_size..((i + 1) * @chunk_size) - 1)
|
|
189
|
+
range = (i * @chunk_size)..(((i + 1) * @chunk_size) - 1)
|
|
162
190
|
yield download_chunk(key, range)
|
|
163
191
|
end
|
|
164
192
|
end
|
|
165
193
|
|
|
194
|
+
def data_size
|
|
195
|
+
if adapter_sqlserver?
|
|
196
|
+
"DATALENGTH(data) AS size"
|
|
197
|
+
elsif adapter_sqlite?
|
|
198
|
+
"LENGTH(data) AS size"
|
|
199
|
+
else
|
|
200
|
+
"OCTET_LENGTH(data) AS size"
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
|
|
166
204
|
def url_helpers
|
|
167
205
|
@url_helpers ||= ::ActiveStorageDB::Engine.routes.url_helpers
|
|
168
206
|
end
|
|
@@ -4,12 +4,15 @@ module ActiveStorage
|
|
|
4
4
|
module DBServiceRails70
|
|
5
5
|
def compose(source_keys, destination_key, **)
|
|
6
6
|
buffer = nil
|
|
7
|
+
comment = "DBService#compose"
|
|
7
8
|
source_keys.each do |source_key|
|
|
8
|
-
|
|
9
|
+
record = ::ActiveStorageDB::File.annotate(comment).select(:data).find_by(ref: source_key)
|
|
10
|
+
raise ActiveStorage::FileNotFoundError unless record
|
|
11
|
+
|
|
9
12
|
if buffer
|
|
10
|
-
buffer << data
|
|
13
|
+
buffer << record.data
|
|
11
14
|
else
|
|
12
|
-
buffer = +data
|
|
15
|
+
buffer = +record.data
|
|
13
16
|
end
|
|
14
17
|
end
|
|
15
18
|
::ActiveStorageDB::File.create!(ref: destination_key, data: buffer) if buffer
|
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module ActiveStorageDB
|
|
4
|
+
# :nocov:
|
|
5
|
+
UNPROCESSABLE_STATUS = if Rails::VERSION::MAJOR > 7 || (Rails::VERSION::MAJOR == 7 && Rails::VERSION::MINOR >= 1)
|
|
6
|
+
:unprocessable_content
|
|
7
|
+
else
|
|
8
|
+
:unprocessable_entity
|
|
9
|
+
end
|
|
10
|
+
# :nocov:
|
|
11
|
+
|
|
4
12
|
class Engine < ::Rails::Engine
|
|
5
13
|
isolate_namespace ActiveStorageDB
|
|
6
14
|
end
|
|
@@ -5,22 +5,38 @@ module ActiveStorage
|
|
|
5
5
|
module_function
|
|
6
6
|
|
|
7
7
|
def print_blob_header(digits: 0)
|
|
8
|
-
puts [
|
|
8
|
+
puts ["Size".rjust(8), "Date".rjust(18), "Id".rjust(digits + 2), " Filename"].join
|
|
9
9
|
end
|
|
10
10
|
|
|
11
11
|
def print_blob(blob, digits: 0)
|
|
12
|
-
size = (blob.byte_size
|
|
13
|
-
date = blob.created_at.strftime(
|
|
14
|
-
puts "#{size}
|
|
12
|
+
size = format_size(blob.byte_size)
|
|
13
|
+
date = blob.created_at.strftime("%Y-%m-%d %H:%M")
|
|
14
|
+
puts "#{size} #{date} #{blob.id.to_s.rjust(digits)} #{blob.filename}"
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def format_size(bytes)
|
|
18
|
+
if bytes >= 1.gigabyte
|
|
19
|
+
"#{(bytes / 1.gigabyte.to_f).round(1)}G".rjust(8)
|
|
20
|
+
elsif bytes >= 1.megabyte
|
|
21
|
+
"#{(bytes / 1.megabyte.to_f).round(1)}M".rjust(8)
|
|
22
|
+
elsif bytes >= 1.kilobyte
|
|
23
|
+
"#{bytes / 1024}K".rjust(8)
|
|
24
|
+
else
|
|
25
|
+
"#{bytes}B".rjust(8)
|
|
26
|
+
end
|
|
15
27
|
end
|
|
16
28
|
end
|
|
17
29
|
end
|
|
18
30
|
|
|
19
31
|
namespace :asdb do
|
|
20
|
-
desc
|
|
21
|
-
task list: [:environment] do |_t,
|
|
22
|
-
|
|
23
|
-
|
|
32
|
+
desc "ActiveStorageDB: list attachments ordered by blob id desc"
|
|
33
|
+
task :list, [:count] => [:environment] do |_t, args|
|
|
34
|
+
count = (args[:count] || 100).to_i
|
|
35
|
+
query = ActiveStorage::Blob.order(id: :desc).limit(count)
|
|
36
|
+
digits = query.ids.inject(0) { |ret, id|
|
|
37
|
+
size = id.to_s.size
|
|
38
|
+
[size, ret].max
|
|
39
|
+
}
|
|
24
40
|
|
|
25
41
|
ActiveStorage::Tasks.print_blob_header(digits: digits)
|
|
26
42
|
query.each do |blob|
|
|
@@ -28,14 +44,14 @@ namespace :asdb do
|
|
|
28
44
|
end
|
|
29
45
|
end
|
|
30
46
|
|
|
31
|
-
desc
|
|
47
|
+
desc "ActiveStorageDB: download attachment by blob id"
|
|
32
48
|
task :download, [:blob_id, :destination] => [:environment] do |_t, args|
|
|
33
49
|
blob_id = args[:blob_id]&.strip
|
|
34
50
|
destination = args[:destination]&.strip || Dir.pwd
|
|
35
|
-
abort(
|
|
51
|
+
abort("Required arguments: source blob id, destination path") if blob_id.blank? || destination.blank?
|
|
36
52
|
|
|
37
53
|
blob = ActiveStorage::Blob.find_by(id: blob_id)
|
|
38
|
-
abort(
|
|
54
|
+
abort("Source file not found") unless blob
|
|
39
55
|
|
|
40
56
|
destination = "#{destination}/#{blob.filename}" if Dir.exist?(destination)
|
|
41
57
|
dir = File.dirname(destination)
|
|
@@ -45,20 +61,23 @@ namespace :asdb do
|
|
|
45
61
|
puts "#{ret} bytes written - #{destination}"
|
|
46
62
|
end
|
|
47
63
|
|
|
48
|
-
desc
|
|
64
|
+
desc "ActiveStorageDB: search attachment by filename (or part of it)"
|
|
49
65
|
task :search, [:filename] => [:environment] do |_t, args|
|
|
50
66
|
filename = args[:filename]&.strip
|
|
51
|
-
abort(
|
|
67
|
+
abort("Required arguments: filename") if filename.blank?
|
|
52
68
|
|
|
53
|
-
blobs = ActiveStorage::Blob.where(
|
|
69
|
+
blobs = ActiveStorage::Blob.where("filename LIKE ?", "%#{ActiveRecord::Base.sanitize_sql_like(filename)}%").order(id: :desc)
|
|
54
70
|
if blobs.any?
|
|
55
|
-
digits = blobs.ids.inject(0) { |ret, id|
|
|
71
|
+
digits = blobs.ids.inject(0) { |ret, id|
|
|
72
|
+
size = id.to_s.size
|
|
73
|
+
[size, ret].max
|
|
74
|
+
}
|
|
56
75
|
ActiveStorage::Tasks.print_blob_header(digits: digits)
|
|
57
76
|
blobs.each do |blob|
|
|
58
77
|
ActiveStorage::Tasks.print_blob(blob, digits: digits)
|
|
59
78
|
end
|
|
60
79
|
else
|
|
61
|
-
puts
|
|
80
|
+
puts "No results"
|
|
62
81
|
end
|
|
63
82
|
end
|
|
64
83
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: active_storage_db
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.6.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Mattia Roccoberton
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: bin
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: activestorage
|
|
@@ -38,34 +37,6 @@ dependencies:
|
|
|
38
37
|
- - ">="
|
|
39
38
|
- !ruby/object:Gem::Version
|
|
40
39
|
version: '6.0'
|
|
41
|
-
- !ruby/object:Gem::Dependency
|
|
42
|
-
name: appraisal
|
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
|
44
|
-
requirements:
|
|
45
|
-
- - "~>"
|
|
46
|
-
- !ruby/object:Gem::Version
|
|
47
|
-
version: '2.4'
|
|
48
|
-
type: :development
|
|
49
|
-
prerelease: false
|
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
-
requirements:
|
|
52
|
-
- - "~>"
|
|
53
|
-
- !ruby/object:Gem::Version
|
|
54
|
-
version: '2.4'
|
|
55
|
-
- !ruby/object:Gem::Dependency
|
|
56
|
-
name: factory_bot_rails
|
|
57
|
-
requirement: !ruby/object:Gem::Requirement
|
|
58
|
-
requirements:
|
|
59
|
-
- - "~>"
|
|
60
|
-
- !ruby/object:Gem::Version
|
|
61
|
-
version: '6.1'
|
|
62
|
-
type: :development
|
|
63
|
-
prerelease: false
|
|
64
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
-
requirements:
|
|
66
|
-
- - "~>"
|
|
67
|
-
- !ruby/object:Gem::Version
|
|
68
|
-
version: '6.1'
|
|
69
40
|
description: An ActiveStorage service plugin to store files in database.
|
|
70
41
|
email:
|
|
71
42
|
- mat@blocknot.es
|
|
@@ -97,7 +68,6 @@ metadata:
|
|
|
97
68
|
homepage_uri: https://github.com/blocknotes/active_storage_db
|
|
98
69
|
source_code_uri: https://github.com/blocknotes/active_storage_db
|
|
99
70
|
rubygems_mfa_required: 'true'
|
|
100
|
-
post_install_message:
|
|
101
71
|
rdoc_options: []
|
|
102
72
|
require_paths:
|
|
103
73
|
- lib
|
|
@@ -112,8 +82,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
112
82
|
- !ruby/object:Gem::Version
|
|
113
83
|
version: '0'
|
|
114
84
|
requirements: []
|
|
115
|
-
rubygems_version: 3.
|
|
116
|
-
signing_key:
|
|
85
|
+
rubygems_version: 3.6.9
|
|
117
86
|
specification_version: 4
|
|
118
87
|
summary: ActiveStorage DB Service
|
|
119
88
|
test_files: []
|