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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8100468edb9adff37d44e1a891e70771a2003d5e
4
- data.tar.gz: d412bfb4ef583d33b7e3014c4723876f7439a4b1
3
+ metadata.gz: e67a83492371a4bbdac7474951277a515bc1f836
4
+ data.tar.gz: 73ec8fb7a9d4ebdfd49522175bc7ccd2d075ad6b
5
5
  SHA512:
6
- metadata.gz: 3adc2ef78fb0770178ea1fa5875ee3bb17724284105a7f6aaabe3b9748321d8264476549f5f528b91589bfcabe59c8882dee5cd60ca01d471da5a83408ee1810
7
- data.tar.gz: e06aa37e00737c58ef4aa443938a2be58ec075b342dcd09154ae84f05bc66c7d837a0ff8cf1a982a49a15a8b095ad6cd94635c98b43e617261bf34ffd7d821d7
6
+ metadata.gz: d2f9cdb78006f2fb7f8e3abf6ec066f77733a1d1a1107671837ff67fd9650762c00beaa49372b718b7e8c8f93a6f8f107897dd7bcac3f6988c30f1ceb5cb452e
7
+ data.tar.gz: a73cfb197b8f2d2a6611a2abaa722741876cec5d91101bfae778bc952c2a3f239cac4a703b3371218e884bc67ec00bd4605017d206f43295c4cb8e3be770023d
@@ -1,7 +1,8 @@
1
1
  require "refile/postgres/version"
2
+ require "refile/postgres/backend"
3
+ require "refile/postgres/backend/reader"
2
4
 
3
5
  module Refile
4
6
  module Postgres
5
- # Your code goes here...
6
7
  end
7
8
  end
@@ -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
+
@@ -1,5 +1,5 @@
1
1
  module Refile
2
2
  module Postgres
3
- VERSION = "0.0.1"
3
+ VERSION = "0.0.2"
4
4
  end
5
5
  end
@@ -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
@@ -0,0 +1,8 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe Refile::Postgres::Backend do
4
+ let(:db_connection) { PG.connect(dbname: 'refile_test') }
5
+ let(:backend) { Refile::Postgres::Backend.new(db_connection, max_size: 100) }
6
+ it_behaves_like :backend
7
+ end
8
+
@@ -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.1
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