refile-postgres 1.1.4 → 1.2.0

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: 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