refile-postgres 0.0.1 → 0.0.2
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/lib/refile/postgres.rb +2 -1
- data/lib/refile/postgres/backend.rb +100 -0
- data/lib/refile/postgres/backend/reader.rb +81 -0
- data/lib/refile/postgres/version.rb +1 -1
- data/refile-postgres.gemspec +6 -0
- data/spec/refile/postgres/backend_spec.rb +8 -0
- data/spec/spec_helper.rb +24 -0
- metadata +78 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e67a83492371a4bbdac7474951277a515bc1f836
|
4
|
+
data.tar.gz: 73ec8fb7a9d4ebdfd49522175bc7ccd2d075ad6b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d2f9cdb78006f2fb7f8e3abf6ec066f77733a1d1a1107671837ff67fd9650762c00beaa49372b718b7e8c8f93a6f8f107897dd7bcac3f6988c30f1ceb5cb452e
|
7
|
+
data.tar.gz: a73cfb197b8f2d2a6611a2abaa722741876cec5d91101bfae778bc952c2a3f239cac4a703b3371218e884bc67ec00bd4605017d206f43295c4cb8e3be770023d
|
data/lib/refile/postgres.rb
CHANGED
@@ -0,0 +1,100 @@
|
|
1
|
+
module Refile
|
2
|
+
module Postgres
|
3
|
+
class Backend
|
4
|
+
DEFAULT_REGISTRY_TABLE = "refile_attachments"
|
5
|
+
DEFAULT_NAMESPACE = "default"
|
6
|
+
PG_LARGE_OBJECT_TABLE = "pg_largeobject"
|
7
|
+
def initialize(connection, max_size: nil, namespace: DEFAULT_NAMESPACE, registry_table: DEFAULT_REGISTRY_TABLE)
|
8
|
+
@connection = connection
|
9
|
+
@namespace = namespace.to_s
|
10
|
+
@registry_table = registry_table
|
11
|
+
@max_size = max_size
|
12
|
+
end
|
13
|
+
|
14
|
+
attr_reader :connection, :namespace, :registry_table
|
15
|
+
|
16
|
+
def upload(uploadable)
|
17
|
+
Refile.verify_uploadable(uploadable, @max_size)
|
18
|
+
oid = connection.lo_creat
|
19
|
+
connection.transaction do
|
20
|
+
begin
|
21
|
+
handle = connection.lo_open(oid, PG::INV_WRITE)
|
22
|
+
connection.lo_truncate(handle, 0)
|
23
|
+
buffer = "" # reuse the same buffer
|
24
|
+
until uploadable.eof?
|
25
|
+
uploadable.read(Refile.read_chunk_size, buffer)
|
26
|
+
connection.lo_write(handle, buffer)
|
27
|
+
end
|
28
|
+
uploadable.close
|
29
|
+
connection.exec_params("INSERT INTO #{registry_table} VALUES ($1::integer, $2::varchar);", [oid, namespace])
|
30
|
+
Refile::File.new(self, oid.to_s)
|
31
|
+
ensure
|
32
|
+
connection.lo_close(handle)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def open(id)
|
38
|
+
Reader.new(connection, id)
|
39
|
+
end
|
40
|
+
|
41
|
+
def read(id)
|
42
|
+
if exists?(id)
|
43
|
+
open(id).read
|
44
|
+
else
|
45
|
+
nil
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def get(id)
|
50
|
+
Refile::File.new(self, id)
|
51
|
+
end
|
52
|
+
|
53
|
+
def exists?(id)
|
54
|
+
connection.exec_params(%{
|
55
|
+
SELECT count(*) FROM #{registry_table}
|
56
|
+
INNER JOIN #{PG_LARGE_OBJECT_TABLE}
|
57
|
+
ON #{registry_table}.id = #{PG_LARGE_OBJECT_TABLE}.loid
|
58
|
+
WHERE #{registry_table}.namespace = $1::varchar
|
59
|
+
AND #{registry_table}.id = $2::integer;
|
60
|
+
}, [namespace, id.to_s.to_i]) do |result|
|
61
|
+
result[0]["count"].to_i > 0
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def size(id)
|
66
|
+
if exists?(id)
|
67
|
+
open(id).size
|
68
|
+
else
|
69
|
+
nil
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def delete(id)
|
74
|
+
if exists?(id)
|
75
|
+
connection.transaction do
|
76
|
+
connection.lo_unlink(id.to_s.to_i)
|
77
|
+
connection.exec_params("DELETE FROM #{registry_table} WHERE id = $1::integer;", [id])
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def clear!(confirm = nil)
|
83
|
+
raise ArgumentError, "are you sure? this will remove all files in the backend, call as `clear!(:confirm)` if you're sure you want to do this" unless confirm == :confirm
|
84
|
+
connection.transaction do
|
85
|
+
connection.exec_params(%{
|
86
|
+
SELECT * FROM #{registry_table}
|
87
|
+
INNER JOIN #{PG_LARGE_OBJECT_TABLE} ON #{registry_table}.id = #{PG_LARGE_OBJECT_TABLE}.loid
|
88
|
+
WHERE #{registry_table}.namespace = $1::varchar;
|
89
|
+
}, [namespace]) do |result|
|
90
|
+
result.each_row do |row|
|
91
|
+
connection.lo_unlink(row[0].to_s.to_i)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
connection.exec_params("DELETE FROM #{registry_table} WHERE namespace = $1::varchar;", [namespace])
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module Refile
|
2
|
+
module Postgres
|
3
|
+
class Backend
|
4
|
+
class Reader
|
5
|
+
PQTRANS_INTRANS = 2 # (idle, within transaction block)
|
6
|
+
|
7
|
+
def initialize(connection, oid)
|
8
|
+
@connection = connection
|
9
|
+
@oid = oid.to_s.to_i
|
10
|
+
@closed = false
|
11
|
+
@pos = 0
|
12
|
+
end
|
13
|
+
|
14
|
+
attr_reader :connection, :oid, :pos
|
15
|
+
|
16
|
+
def read(length = nil, buffer = nil)
|
17
|
+
result = if length
|
18
|
+
raise "closed" if @closed
|
19
|
+
smart_transaction do |descriptor|
|
20
|
+
connection.lo_lseek(descriptor, @pos, PG::SEEK_SET)
|
21
|
+
data = connection.lo_read(descriptor, length)
|
22
|
+
@pos = connection.lo_tell(descriptor)
|
23
|
+
data
|
24
|
+
end
|
25
|
+
else
|
26
|
+
smart_transaction do |descriptor|
|
27
|
+
connection.lo_read(descriptor, size)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
buffer.replace(result) if buffer and result
|
31
|
+
result
|
32
|
+
end
|
33
|
+
|
34
|
+
def eof?
|
35
|
+
smart_transaction do |descriptor|
|
36
|
+
@pos == size
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def size
|
41
|
+
@size ||= smart_transaction do |descriptor|
|
42
|
+
current_position = connection.lo_tell(descriptor)
|
43
|
+
end_position = connection.lo_lseek(descriptor, 0, PG::SEEK_END)
|
44
|
+
connection.lo_lseek(descriptor, current_position, PG::SEEK_SET)
|
45
|
+
end_position
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def close
|
50
|
+
@closed = true
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def smart_transaction
|
56
|
+
result = nil
|
57
|
+
ensure_in_transaction do
|
58
|
+
begin
|
59
|
+
handle = connection.lo_open(oid)
|
60
|
+
result = yield handle
|
61
|
+
connection.lo_close(handle)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
result
|
65
|
+
end
|
66
|
+
|
67
|
+
def ensure_in_transaction
|
68
|
+
if connection.transaction_status == PQTRANS_INTRANS
|
69
|
+
yield
|
70
|
+
else
|
71
|
+
connection.transaction do
|
72
|
+
yield
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
|
data/refile-postgres.gemspec
CHANGED
@@ -18,6 +18,12 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
|
+
spec.add_dependency "refile"
|
22
|
+
spec.add_dependency "pg"
|
23
|
+
|
21
24
|
spec.add_development_dependency "bundler", "~> 1.7"
|
25
|
+
spec.add_development_dependency "pry"
|
26
|
+
spec.add_development_dependency "pry-stack_explorer"
|
27
|
+
spec.add_development_dependency "rails", "~> 4.1.8"
|
22
28
|
spec.add_development_dependency "rake", "~> 10.0"
|
23
29
|
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.join(Gem::Specification.find_by_name("refile").gem_dir, "spec"))
|
2
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
3
|
+
require "refile/spec_helper"
|
4
|
+
require "pg"
|
5
|
+
require "refile/postgres"
|
6
|
+
|
7
|
+
RSpec.configure do |config|
|
8
|
+
config.before(:all) do
|
9
|
+
DB_NAME = 'refile_test'
|
10
|
+
connection = PG.connect(dbname: DB_NAME)
|
11
|
+
connection.exec %{ DROP TABLE IF EXISTS #{Refile::Postgres::Backend::DEFAULT_REGISTRY_TABLE} CASCADE; }
|
12
|
+
connection.exec %{
|
13
|
+
CREATE TABLE IF NOT EXISTS #{Refile::Postgres::Backend::DEFAULT_REGISTRY_TABLE}
|
14
|
+
(
|
15
|
+
id serial NOT NULL,
|
16
|
+
namespace character varying(255),
|
17
|
+
CONSTRAINT refile_backend_lo_oids_pkey PRIMARY KEY (id)
|
18
|
+
)
|
19
|
+
WITH(
|
20
|
+
OIDS=FALSE
|
21
|
+
);
|
22
|
+
}
|
23
|
+
end
|
24
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: refile-postgres
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Krists Ozols
|
@@ -10,6 +10,34 @@ bindir: bin
|
|
10
10
|
cert_chain: []
|
11
11
|
date: 2014-12-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: refile
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: pg
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
13
41
|
- !ruby/object:Gem::Dependency
|
14
42
|
name: bundler
|
15
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -24,6 +52,48 @@ dependencies:
|
|
24
52
|
- - "~>"
|
25
53
|
- !ruby/object:Gem::Version
|
26
54
|
version: '1.7'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: pry
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: pry-stack_explorer
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rails
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 4.1.8
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 4.1.8
|
27
97
|
- !ruby/object:Gem::Dependency
|
28
98
|
name: rake
|
29
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -52,8 +122,12 @@ files:
|
|
52
122
|
- README.md
|
53
123
|
- Rakefile
|
54
124
|
- lib/refile/postgres.rb
|
125
|
+
- lib/refile/postgres/backend.rb
|
126
|
+
- lib/refile/postgres/backend/reader.rb
|
55
127
|
- lib/refile/postgres/version.rb
|
56
128
|
- refile-postgres.gemspec
|
129
|
+
- spec/refile/postgres/backend_spec.rb
|
130
|
+
- spec/spec_helper.rb
|
57
131
|
homepage: https://github.com/krists/refile-postgres
|
58
132
|
licenses:
|
59
133
|
- MIT
|
@@ -78,4 +152,6 @@ rubygems_version: 2.4.2
|
|
78
152
|
signing_key:
|
79
153
|
specification_version: 4
|
80
154
|
summary: Postgres database as a backend for Refile
|
81
|
-
test_files:
|
155
|
+
test_files:
|
156
|
+
- spec/refile/postgres/backend_spec.rb
|
157
|
+
- spec/spec_helper.rb
|