refile-postgres 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
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