active_storage-postgresql 0.1.0 → 0.1.1
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 +5 -2
- data/lib/active_storage/postgresql/file.rb +42 -13
- data/lib/active_storage/postgresql/version.rb +1 -1
- data/lib/active_storage/service/postgresql_service.rb +17 -35
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8e03540828022cafb6f37bcb926ed367951072e40af4970f51809b796e5fc8d5
|
4
|
+
data.tar.gz: 369c7335dfbb46aa1add165303bbb8c505600df7be8dc08663968b35884a08d5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ffc0882ec92da092e0954498f3815367b9d52b6329e4aae764531cb888ffdd22b87ebaffd8189acb3c2750db71af0badf632642c57b3fd5ff30d80dc22100042
|
7
|
+
data.tar.gz: 9e4aabe7a6cd2dbf777749078db3e2d382ff385067bdd045883d5a3b56cab9bbc5dbe3926f191451c394677b2d4e76f7e00c315c82772ff8a9a1d86561823bd9
|
data/README.md
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
# ActiveStorage::PostgreSQL
|
2
2
|
|
3
|
+
[](https://badge.fury.io/rb/active_storage-postgresql)
|
4
|
+
[](https://travis-ci.com/lsylvester/active_storage-postgresql)
|
5
|
+
|
3
6
|
ActiveStorage Service to store files PostgeSQL.
|
4
7
|
|
5
8
|
Files are stored in PostgreSQL as Large Objects, which provide streaming style access.
|
@@ -7,13 +10,13 @@ More information about Large Objects can be found [here](https://www.postgresql.
|
|
7
10
|
|
8
11
|
This allows use of ActiveStorage on hosting platforms with ephemeral file systems such as Heroku without relying on third party storage services.
|
9
12
|
|
10
|
-
There are [some limits](https://dba.stackexchange.com/questions/127270/what-are-the-limits-of-postgresqls-large-object-facility) to the storage of Large Objects in PostgerSQL, so this is only recommended for prototyping and very small sites.
|
13
|
+
There are [some limits](https://dba.stackexchange.com/questions/127270/what-are-the-limits-of-postgresqls-large-object-facility) to the storage of Large Objects in PostgerSQL, so this is only recommended for prototyping and very small sites.
|
11
14
|
|
12
15
|
## Installation
|
13
16
|
Add this line to your application's Gemfile:
|
14
17
|
|
15
18
|
```ruby
|
16
|
-
gem 'active_storage-postgresql'
|
19
|
+
gem 'active_storage-postgresql'
|
17
20
|
```
|
18
21
|
|
19
22
|
And then execute:
|
@@ -1,8 +1,31 @@
|
|
1
1
|
class ActiveStorage::PostgreSQL::File < ActiveRecord::Base
|
2
2
|
self.table_name = "active_storage_postgresql_files"
|
3
3
|
|
4
|
-
|
5
|
-
|
4
|
+
attribute :oid, :integer, default: ->{ connection.raw_connection.lo_creat }
|
5
|
+
attr_accessor :checksum, :io
|
6
|
+
attr_writer :digest
|
7
|
+
|
8
|
+
def digest
|
9
|
+
@digest ||= Digest::MD5.new
|
10
|
+
end
|
11
|
+
|
12
|
+
before_create :write_or_import, if: :io
|
13
|
+
before_create :verify_checksum, if: :checksum
|
14
|
+
|
15
|
+
def write_or_import
|
16
|
+
if io.respond_to?(:to_path)
|
17
|
+
import(io.to_path)
|
18
|
+
else
|
19
|
+
open(::PG::INV_WRITE) do |file|
|
20
|
+
while data = io.read(5.megabytes)
|
21
|
+
write(data)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def verify_checksum
|
28
|
+
raise ActiveStorage::IntegrityError unless digest.base64digest == checksum
|
6
29
|
end
|
7
30
|
|
8
31
|
def self.open(key, &block)
|
@@ -22,34 +45,40 @@ class ActiveStorage::PostgreSQL::File < ActiveRecord::Base
|
|
22
45
|
|
23
46
|
def write(content)
|
24
47
|
lo_write(@lo, content)
|
48
|
+
digest.update(content)
|
25
49
|
end
|
26
50
|
|
27
51
|
def read(bytes=size)
|
28
52
|
lo_read(@lo, bytes)
|
29
53
|
end
|
30
54
|
|
31
|
-
def seek(position)
|
32
|
-
lo_seek(@lo, position,
|
55
|
+
def seek(position, whence=PG::SEEK_SET)
|
56
|
+
lo_seek(@lo, position, whence)
|
33
57
|
end
|
34
58
|
|
35
59
|
def import(path)
|
36
|
-
|
37
|
-
|
38
|
-
|
60
|
+
self.oid = lo_import(path)
|
61
|
+
self.digest = Digest::MD5.file(path)
|
62
|
+
end
|
63
|
+
|
64
|
+
def tell
|
65
|
+
lo_tell(@lo)
|
39
66
|
end
|
40
67
|
|
41
68
|
def size
|
42
|
-
current_position =
|
43
|
-
|
44
|
-
|
45
|
-
|
69
|
+
current_position = tell
|
70
|
+
seek(0, PG::SEEK_END)
|
71
|
+
tell.tap do
|
72
|
+
seek(current_position)
|
46
73
|
end
|
47
74
|
end
|
48
75
|
|
49
|
-
|
50
|
-
|
76
|
+
def unlink
|
77
|
+
lo_unlink(oid)
|
51
78
|
end
|
52
79
|
|
80
|
+
before_destroy :unlink
|
81
|
+
|
53
82
|
delegate :lo_seek, :lo_tell, :lo_import, :lo_read, :lo_write, :lo_open,
|
54
83
|
:lo_unlink, :lo_close, :lo_creat, to: 'self.class.connection.raw_connection'
|
55
84
|
|
@@ -9,33 +9,9 @@ module ActiveStorage
|
|
9
9
|
def initialize(**options)
|
10
10
|
end
|
11
11
|
|
12
|
-
def upload(key, io, checksum: nil)
|
12
|
+
def upload(key, io, checksum: nil, **)
|
13
13
|
instrument :upload, key: key, checksum: checksum do
|
14
|
-
|
15
|
-
ActiveStorage::PostgreSQL::File.create!(key: key) do |file|
|
16
|
-
file.import(io.to_path)
|
17
|
-
end
|
18
|
-
if checksum
|
19
|
-
unless Digest::MD5.file(io.to_path).base64digest == checksum
|
20
|
-
delete key
|
21
|
-
raise ActiveStorage::IntegrityError
|
22
|
-
end
|
23
|
-
end
|
24
|
-
else
|
25
|
-
md5 = Digest::MD5.new
|
26
|
-
ActiveStorage::PostgreSQL::File.create!(key: key).open(::PG::INV_WRITE) do |file|
|
27
|
-
while data = io.read(5.megabytes)
|
28
|
-
md5.update(data)
|
29
|
-
file.write(data)
|
30
|
-
end
|
31
|
-
end
|
32
|
-
if checksum
|
33
|
-
unless md5.base64digest == checksum
|
34
|
-
delete key
|
35
|
-
raise ActiveStorage::IntegrityError
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
14
|
+
ActiveStorage::PostgreSQL::File.create!(key: key, io: io, checksum: checksum)
|
39
15
|
end
|
40
16
|
end
|
41
17
|
|
@@ -88,17 +64,23 @@ module ActiveStorage
|
|
88
64
|
|
89
65
|
def url(key, expires_in:, filename:, disposition:, content_type:)
|
90
66
|
instrument :url, key: key do |payload|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
host: current_host,
|
97
|
-
filename: filename,
|
98
|
-
disposition: content_disposition_with(type: disposition, filename: filename),
|
67
|
+
content_disposition = content_disposition_with(type: disposition, filename: filename)
|
68
|
+
verified_key_with_expiration = ActiveStorage.verifier.generate(
|
69
|
+
{
|
70
|
+
key: key,
|
71
|
+
disposition: content_disposition,
|
99
72
|
content_type: content_type
|
100
|
-
|
73
|
+
},
|
74
|
+
{ expires_in: expires_in,
|
75
|
+
purpose: :blob_key }
|
76
|
+
)
|
101
77
|
|
78
|
+
generated_url = url_helpers.rails_disk_service_url(verified_key_with_expiration,
|
79
|
+
host: current_host,
|
80
|
+
disposition: content_disposition,
|
81
|
+
content_type: content_type,
|
82
|
+
filename: filename
|
83
|
+
)
|
102
84
|
payload[:url] = generated_url
|
103
85
|
|
104
86
|
generated_url
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: active_storage-postgresql
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Lachlan Sylvester
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-11-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -104,7 +104,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
104
104
|
version: '0'
|
105
105
|
requirements: []
|
106
106
|
rubyforge_project:
|
107
|
-
rubygems_version: 2.7.
|
107
|
+
rubygems_version: 2.7.6
|
108
108
|
signing_key:
|
109
109
|
specification_version: 4
|
110
110
|
summary: PostgreSQL Adapter for Active Storage
|