refile-postgres 1.1.4 → 1.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5eea1ec5fdd88b38c8f5221c8d9eede03fb9c0a3
4
- data.tar.gz: 067ee32e83155a481abf2d0b38b4531f8a733974
3
+ metadata.gz: dcbf870ad7c94880999b64a72c48264070344114
4
+ data.tar.gz: e9015db34ee5fcc3e39963894d9b1fe2c3bc4827
5
5
  SHA512:
6
- metadata.gz: eec4a40d70414902996a7107051988ede96e464c8b516eb12821e6730d71110cd17ed6004056227b533d75c947589bae25d65364652ec6f0e1ffd349ccc98beb
7
- data.tar.gz: db89250b2da99292177d85e634c10634b507c7698119782e9990558269a26af05296881cada8112f1ab36bb9f0cd200f65c8d8b6f0b5c2db987f5d9f9c68fc52
6
+ metadata.gz: 8164bf9a9cd8dc25d88c809490ba28ed3dd9b1b997da8a892a9a30022c39cfe0dba14ecbc574f2744392b5950a0f9b095308d10cd4e163e102f62d0c855522a7
7
+ data.tar.gz: 0a84dff267e690011f4a219042b6e674409fa1249555671ca248e8dd52c8f073afc0bdd2e92afc1111d711266cf828619386316088cf4188550b35ec1fc2a7dc
@@ -1,4 +1,5 @@
1
1
  require "refile"
2
2
  Refile.configure do |config|
3
- config.store = Refile::Postgres::Backend.new(proc { ActiveRecord::Base.connection.raw_connection } )
3
+ connection = lambda { |&blk| ActiveRecord::Base.connection_pool.with_connection { |con| blk.call(con.raw_connection) } }
4
+ config.store = Refile::Postgres::Backend.new(connection)
4
5
  end
@@ -4,27 +4,31 @@ module Refile
4
4
  class Reader
5
5
  include SmartTransaction
6
6
 
7
- def initialize(connection, oid)
8
- @connection = connection
7
+ def initialize(connection_or_proc, oid)
8
+ @connection_or_proc = connection_or_proc
9
9
  @oid = oid.to_s.to_i
10
10
  @closed = false
11
11
  @pos = 0
12
12
  end
13
13
 
14
- attr_reader :connection, :oid, :pos
14
+ attr_reader :oid, :pos
15
15
 
16
16
  def read(length = nil, buffer = nil)
17
17
  result = if length
18
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
19
+ with_connection do |connection|
20
+ smart_transaction(connection) do |descriptor|
21
+ connection.lo_lseek(descriptor, @pos, PG::SEEK_SET)
22
+ data = connection.lo_read(descriptor, length)
23
+ @pos = connection.lo_tell(descriptor)
24
+ data
25
+ end
24
26
  end
25
27
  else
26
- smart_transaction do |descriptor|
27
- connection.lo_read(descriptor, size)
28
+ with_connection do |connection|
29
+ smart_transaction(connection) do |descriptor|
30
+ connection.lo_read(descriptor, size)
31
+ end
28
32
  end
29
33
  end
30
34
  buffer.replace(result) if buffer and result
@@ -32,24 +36,34 @@ module Refile
32
36
  end
33
37
 
34
38
  def eof?
35
- smart_transaction do |descriptor|
36
- @pos == size
39
+ with_connection do |connection|
40
+ smart_transaction(connection) do |descriptor|
41
+ @pos == size
42
+ end
37
43
  end
38
44
  end
39
45
 
40
46
  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
+ @size ||= fetch_size
47
48
  end
48
49
 
49
50
  def close
50
51
  @closed = true
51
52
  end
52
53
 
54
+ private
55
+
56
+ def fetch_size
57
+ with_connection do |connection|
58
+ smart_transaction(connection) do |descriptor|
59
+ current_position = connection.lo_tell(descriptor)
60
+ end_position = connection.lo_lseek(descriptor, 0, PG::SEEK_END)
61
+ connection.lo_lseek(descriptor, current_position, PG::SEEK_SET)
62
+ end_position
63
+ end
64
+ end
65
+ end
66
+
53
67
  end
54
68
  end
55
69
  end
@@ -8,7 +8,6 @@ module Refile
8
8
  DEFAULT_NAMESPACE = "default"
9
9
  PG_LARGE_OBJECT_METADATA_TABLE = "pg_largeobject_metadata"
10
10
  READ_CHUNK_SIZE = 3000
11
- INIT_CONNECTION_ARG_ERROR_MSG = "When initializing new Refile::Postgres::Backend first argument should be an instance of PG::Connection or a lambda/proc that returns it. When using ActiveRecord it is available as ActiveRecord::Base.connection.raw_connection"
12
11
 
13
12
  def initialize(connection_or_proc, max_size: nil, namespace: DEFAULT_NAMESPACE, registry_table: DEFAULT_REGISTRY_TABLE)
14
13
  @connection_or_proc = connection_or_proc
@@ -22,12 +21,11 @@ module Refile
22
21
 
23
22
  def registry_table
24
23
  unless @registry_table_validated
25
- connection.exec %{
26
- SELECT count(*) from pg_catalog.pg_tables
27
- WHERE tablename = '#{@registry_table}';
28
- } do |result|
29
- unless result[0]["count"].to_i > 0
30
- raise RegistryTableDoesNotExistError.new(%{Please create a table "#{@registry_table}" where backend could store list of attachments})
24
+ with_connection do |connection|
25
+ connection.exec_params("SELECT * FROM pg_catalog.pg_tables WHERE tablename = $1::varchar;", [@registry_table]) do |result|
26
+ if result.count != 1
27
+ raise RegistryTableDoesNotExistError.new(%{Please create a table "#{@registry_table}" where backend could store list of attachments})
28
+ end
31
29
  end
32
30
  end
33
31
  @registry_table_validated = true
@@ -35,37 +33,31 @@ module Refile
35
33
  @registry_table
36
34
  end
37
35
 
38
- def connection
39
- if has_active_connection?
40
- @connection
41
- else
42
- obtain_new_connection
43
- end
44
- end
45
-
46
36
  verify_uploadable def upload(uploadable)
47
- oid = connection.lo_creat
48
- ensure_in_transaction do
49
- begin
50
- handle = connection.lo_open(oid, PG::INV_WRITE)
51
- connection.lo_truncate(handle, 0)
52
- buffer = "" # reuse the same buffer
53
- until uploadable.eof?
54
- uploadable.read(READ_CHUNK_SIZE, buffer)
55
- connection.lo_write(handle, buffer)
37
+ with_connection do |connection|
38
+ oid = connection.lo_creat
39
+ ensure_in_transaction(connection) do
40
+ begin
41
+ handle = connection.lo_open(oid, PG::INV_WRITE)
42
+ connection.lo_truncate(handle, 0)
43
+ buffer = "" # reuse the same buffer
44
+ until uploadable.eof?
45
+ uploadable.read(READ_CHUNK_SIZE, buffer)
46
+ connection.lo_write(handle, buffer)
47
+ end
48
+ uploadable.close
49
+ connection.exec_params("INSERT INTO #{registry_table} VALUES ($1::integer, $2::varchar);", [oid, namespace])
50
+ Refile::File.new(self, oid.to_s)
51
+ ensure
52
+ connection.lo_close(handle)
56
53
  end
57
- uploadable.close
58
- connection.exec_params("INSERT INTO #{registry_table} VALUES ($1::integer, $2::varchar);", [oid, namespace])
59
- Refile::File.new(self, oid.to_s)
60
- ensure
61
- connection.lo_close(handle)
62
54
  end
63
55
  end
64
56
  end
65
57
 
66
58
  verify_id def open(id)
67
59
  if exists?(id)
68
- Reader.new(connection, id)
60
+ Reader.new(@connection_or_proc, id)
69
61
  else
70
62
  raise ArgumentError.new("No such attachment with ID: #{id}")
71
63
  end
@@ -84,14 +76,16 @@ module Refile
84
76
  end
85
77
 
86
78
  verify_id def exists?(id)
87
- connection.exec_params(%{
88
- SELECT count(*) FROM #{registry_table}
89
- INNER JOIN #{PG_LARGE_OBJECT_METADATA_TABLE}
90
- ON #{registry_table}.id = #{PG_LARGE_OBJECT_METADATA_TABLE}.oid
91
- WHERE #{registry_table}.namespace = $1::varchar
92
- AND #{registry_table}.id = $2::integer;
93
- }, [namespace, id.to_s.to_i]) do |result|
94
- result[0]["count"].to_i > 0
79
+ with_connection do |connection|
80
+ connection.exec_params(%{
81
+ SELECT count(*) FROM #{registry_table}
82
+ INNER JOIN #{PG_LARGE_OBJECT_METADATA_TABLE}
83
+ ON #{registry_table}.id = #{PG_LARGE_OBJECT_METADATA_TABLE}.oid
84
+ WHERE #{registry_table}.namespace = $1::varchar
85
+ AND #{registry_table}.id = $2::integer;
86
+ }, [namespace, id.to_s.to_i]) do |result|
87
+ result[0]["count"].to_i > 0
88
+ end
95
89
  end
96
90
  end
97
91
 
@@ -105,9 +99,11 @@ module Refile
105
99
 
106
100
  verify_id def delete(id)
107
101
  if exists?(id)
108
- ensure_in_transaction do
109
- connection.lo_unlink(id.to_s.to_i)
110
- connection.exec_params("DELETE FROM #{registry_table} WHERE id = $1::integer;", [id])
102
+ with_connection do |connection|
103
+ ensure_in_transaction(connection) do
104
+ connection.lo_unlink(id.to_s.to_i)
105
+ connection.exec_params("DELETE FROM #{registry_table} WHERE id = $1::integer;", [id])
106
+ end
111
107
  end
112
108
  end
113
109
  end
@@ -115,33 +111,22 @@ module Refile
115
111
  def clear!(confirm = nil)
116
112
  raise Refile::Confirm unless confirm == :confirm
117
113
  registry_table
118
- ensure_in_transaction do
119
- connection.exec_params(%{
120
- SELECT * FROM #{registry_table}
121
- INNER JOIN #{PG_LARGE_OBJECT_METADATA_TABLE} ON #{registry_table}.id = #{PG_LARGE_OBJECT_METADATA_TABLE}.oid
122
- WHERE #{registry_table}.namespace = $1::varchar;
123
- }, [namespace]) do |result|
124
- result.each_row do |row|
125
- connection.lo_unlink(row[0].to_s.to_i)
114
+ with_connection do |connection|
115
+ ensure_in_transaction(connection) do
116
+ connection.exec_params(%{
117
+ SELECT * FROM #{registry_table}
118
+ INNER JOIN #{PG_LARGE_OBJECT_METADATA_TABLE} ON #{registry_table}.id = #{PG_LARGE_OBJECT_METADATA_TABLE}.oid
119
+ WHERE #{registry_table}.namespace = $1::varchar;
120
+ }, [namespace]) do |result|
121
+ result.each_row do |row|
122
+ connection.lo_unlink(row[0].to_s.to_i)
123
+ end
126
124
  end
125
+ connection.exec_params("DELETE FROM #{registry_table} WHERE namespace = $1::varchar;", [namespace])
127
126
  end
128
- connection.exec_params("DELETE FROM #{registry_table} WHERE namespace = $1::varchar;", [namespace])
129
127
  end
130
128
  end
131
129
 
132
- private
133
-
134
- def has_active_connection?
135
- @connection && !@connection.finished?
136
- end
137
-
138
- def obtain_new_connection
139
- candidate = @connection_or_proc.is_a?(Proc) ? @connection_or_proc.call : @connection_or_proc
140
- unless candidate.is_a?(PG::Connection)
141
- raise ArgumentError.new(INIT_CONNECTION_ARG_ERROR_MSG)
142
- end
143
- @connection = candidate
144
- end
145
130
  end
146
131
  end
147
132
  end
@@ -1,12 +1,12 @@
1
1
  module Refile
2
2
  module Postgres
3
3
  module SmartTransaction
4
-
4
+ INIT_CONNECTION_ARG_ERROR_MSG = "When initializing new Refile::Postgres::Backend first argument should be an instance of PG::Connection or a lambda/proc that yields it."
5
5
  PQTRANS_INTRANS = 2 # (idle, within transaction block)
6
6
 
7
- def smart_transaction
7
+ def smart_transaction(connection)
8
8
  result = nil
9
- ensure_in_transaction do
9
+ ensure_in_transaction(connection) do
10
10
  begin
11
11
  handle = connection.lo_open(oid)
12
12
  result = yield handle
@@ -16,7 +16,7 @@ module Refile
16
16
  result
17
17
  end
18
18
 
19
- def ensure_in_transaction
19
+ def ensure_in_transaction(connection)
20
20
  if connection.transaction_status == PQTRANS_INTRANS
21
21
  yield
22
22
  else
@@ -26,6 +26,26 @@ module Refile
26
26
  end
27
27
  end
28
28
 
29
+ def with_connection
30
+ if @connection_or_proc.is_a?(PG::Connection)
31
+ yield @connection_or_proc
32
+ else
33
+ if @connection_or_proc.is_a?(Proc)
34
+ block_has_been_executed = false
35
+ value = nil
36
+ @connection_or_proc.call do |connection|
37
+ block_has_been_executed = true
38
+ raise ArgumentError.new(INIT_CONNECTION_ARG_ERROR_MSG) unless connection.is_a?(PG::Connection)
39
+ value = yield connection
40
+ end
41
+ raise ArgumentError.new(INIT_CONNECTION_ARG_ERROR_MSG) unless block_has_been_executed
42
+ value
43
+ else
44
+ raise ArgumentError.new(INIT_CONNECTION_ARG_ERROR_MSG)
45
+ end
46
+ end
47
+ end
48
+
29
49
  end
30
50
  end
31
51
  end
@@ -1,5 +1,5 @@
1
1
  module Refile
2
2
  module Postgres
3
- VERSION = "1.1.4"
3
+ VERSION = "1.2.0"
4
4
  end
5
5
  end
@@ -18,7 +18,7 @@ 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", "~> 0.6.1"
21
+ spec.add_dependency "refile", "~> 0.6.2"
22
22
  spec.add_dependency "pg"
23
23
 
24
24
  spec.add_development_dependency "bundler"
@@ -26,7 +26,7 @@ Gem::Specification.new do |spec|
26
26
  spec.add_development_dependency "webmock"
27
27
  spec.add_development_dependency "pry"
28
28
  spec.add_development_dependency "pry-stack_explorer"
29
- spec.add_development_dependency "rails", "~> 4.2.1"
29
+ spec.add_development_dependency "rails", "~> 4.2.5"
30
30
  spec.add_development_dependency "rake"
31
31
  spec.add_development_dependency "codeclimate-test-reporter"
32
32
  end
@@ -1,47 +1,37 @@
1
1
  require "spec_helper"
2
2
 
3
- RSpec.describe Refile::Postgres::Backend do
4
- let(:connection_or_proc) { PG.connect(dbname: 'refile_test') }
3
+ describe Refile::Postgres::Backend do
4
+ let(:connection) { PG.connect(dbname: 'refile_test') }
5
5
  let(:backend) { Refile::Postgres::Backend.new(connection_or_proc, max_size: 100) }
6
- it_behaves_like :backend
7
6
 
8
7
  context "Connection tests" do
9
- def connection
10
- PG.connect(dbname: 'refile_test')
8
+ context "when not using procs and providing PG::Connection directly" do
9
+ let(:connection_or_proc) { connection }
10
+ it "reuses the same PG::Connection" do
11
+ expect(backend.with_connection { |c| c.db }).to eq("refile_test")
12
+ end
11
13
  end
12
14
 
13
15
  context "when using proc" do
14
- def connection_or_proc
15
- proc { connection }
16
- end
17
-
18
- it "reuses the same PG::Connection if connection is ok" do
19
- expect(backend.connection).to eq(backend.connection)
16
+ context "when lambda does not yield a block but returns connection" do
17
+ let(:connection_or_proc) { lambda { connection } }
18
+ it "raises argument error" do
19
+ expect {
20
+ backend.with_connection { |c| c.db }
21
+ }.to raise_error(ArgumentError, "When initializing new Refile::Postgres::Backend first argument should be an instance of PG::Connection or a lambda/proc that yields it.")
22
+ end
20
23
  end
21
-
22
- it "executes proc and obtains new connection if old one is closed" do
23
- old = backend.connection
24
- old.close
25
- expect(backend.connection).not_to eq(old)
26
- expect(backend.connection.finished?).to be_falsey
24
+ context "when lambda does yield a PG::Connection" do
25
+ let(:connection_or_proc) { lambda { |&blk| blk.call(connection) } }
26
+ it "is usable in queries" do
27
+ expect(backend.with_connection { |c| c.db }).to eq("refile_test")
28
+ end
27
29
  end
28
30
  end
31
+ end
29
32
 
30
- context "when not using procs and providing PG::Connection directly" do
31
- def connection_or_proc
32
- connection
33
- end
34
-
35
- it "reuses the same PG::Connection" do
36
- expect(backend.connection).to eq(backend.connection)
37
- end
38
-
39
- it "continues to use old connection if the old one is closed" do
40
- old = backend.connection
41
- old.close
42
- expect(backend.connection).to eq(old)
43
- expect(backend.connection.finished?).to be_truthy
44
- end
45
- end
33
+ context "Refile Provided tests" do
34
+ let(:connection_or_proc) { connection }
35
+ it_behaves_like :backend
46
36
  end
47
37
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: refile-postgres
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.4
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Krists Ozols
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-09-21 00:00:00.000000000 Z
11
+ date: 2015-12-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: refile
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 0.6.1
19
+ version: 0.6.2
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 0.6.1
26
+ version: 0.6.2
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: pg
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -114,14 +114,14 @@ dependencies:
114
114
  requirements:
115
115
  - - "~>"
116
116
  - !ruby/object:Gem::Version
117
- version: 4.2.1
117
+ version: 4.2.5
118
118
  type: :development
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
122
  - - "~>"
123
123
  - !ruby/object:Gem::Version
124
- version: 4.2.1
124
+ version: 4.2.5
125
125
  - !ruby/object:Gem::Dependency
126
126
  name: rake
127
127
  requirement: !ruby/object:Gem::Requirement