dis 1.3.1 → 2.1.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 +4 -4
- data/README.md +22 -2
- data/lib/dis/controller.rb +60 -0
- data/lib/dis/response_body.rb +45 -0
- data/lib/dis/version.rb +1 -1
- data/lib/dis.rb +3 -0
- metadata +4 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b78f0ff03e09c43d839c8ba8e119c6548ae518469d17d6646767c987f36f6a15
|
|
4
|
+
data.tar.gz: 3c9d88b627d1eadb871f926a2552e9761eb007442543db0aa65f88623e00f168
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7987a1138a986daa040447ff607a07b6bf077a0ea0450274dafbff3b977cca1fee9bdf2121847c9492ffe75fe12b7bb11fc8a056240d473a69129e205ca821af
|
|
7
|
+
data.tar.gz: 888c70668ce77b47451359d5cfe953793488eb1238749eaa0f7151e6779ed105ff6a1941cd9b8e3d69419c24a349c022fc857cea443bb48b48f102f4711507bf
|
data/README.md
CHANGED
|
@@ -125,8 +125,7 @@ document.with_data_file { |path| Vips::Image.new_from_file(path.to_s).avg }
|
|
|
125
125
|
|
|
126
126
|
`open_data` returns an open file, valid until you close it — even if
|
|
127
127
|
the content is deleted or evicted from a cache layer meanwhile. Use it
|
|
128
|
-
when the reader outlives the current call stack
|
|
129
|
-
body handed to the web server.
|
|
128
|
+
when the reader outlives the current call stack.
|
|
130
129
|
|
|
131
130
|
```ruby
|
|
132
131
|
document.open_data { |file| file.read }
|
|
@@ -134,6 +133,27 @@ document.open_data { |file| file.read }
|
|
|
134
133
|
file = document.open_data # caller closes it
|
|
135
134
|
```
|
|
136
135
|
|
|
136
|
+
### Sending data from a controller
|
|
137
|
+
|
|
138
|
+
Include `Dis::Controller` and use `send_dis_data` to stream a record's
|
|
139
|
+
data to the client. It works like `send_file`, but reads through an
|
|
140
|
+
open descriptor rather than a path, so the response is unaffected if
|
|
141
|
+
the content is evicted or deleted while it is being written.
|
|
142
|
+
|
|
143
|
+
```ruby
|
|
144
|
+
class DocumentsController < ApplicationController
|
|
145
|
+
include Dis::Controller
|
|
146
|
+
|
|
147
|
+
def show
|
|
148
|
+
send_dis_data(Document.find(params[:id]), disposition: "inline")
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
`filename` and `content_type` default to the record's own metadata.
|
|
154
|
+
The full set of options is `filename`, `content_type`, `disposition`
|
|
155
|
+
and `status`.
|
|
156
|
+
|
|
137
157
|
## Layers
|
|
138
158
|
|
|
139
159
|
The underlying storage consists of one or more layers. Each layer
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Dis
|
|
4
|
+
# = Dis Controller
|
|
5
|
+
#
|
|
6
|
+
# Adds {#send_dis_data} for serving stored data from a controller.
|
|
7
|
+
#
|
|
8
|
+
# class DocumentsController < ApplicationController
|
|
9
|
+
# include Dis::Controller
|
|
10
|
+
#
|
|
11
|
+
# def show
|
|
12
|
+
# send_dis_data(Document.find(params[:id]))
|
|
13
|
+
# end
|
|
14
|
+
# end
|
|
15
|
+
module Controller
|
|
16
|
+
extend ActiveSupport::Concern
|
|
17
|
+
|
|
18
|
+
included do
|
|
19
|
+
include ActionController::DataStreaming
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
private
|
|
23
|
+
|
|
24
|
+
# Sends the record's data to the client. Works like +send_file+,
|
|
25
|
+
# but reads through an open descriptor rather than a path, so the
|
|
26
|
+
# response is unaffected if the content is evicted or deleted
|
|
27
|
+
# while it is being written.
|
|
28
|
+
#
|
|
29
|
+
# +filename+ and +content_type+ default to the record's own
|
|
30
|
+
# metadata.
|
|
31
|
+
#
|
|
32
|
+
# @param record [Dis::Model] the record to send data from
|
|
33
|
+
# @param filename [String, nil] suggested filename
|
|
34
|
+
# @param content_type [String, nil] the content type
|
|
35
|
+
# @param disposition [String] +"attachment"+ or +"inline"+
|
|
36
|
+
# @param status [Integer] the HTTP status code
|
|
37
|
+
# @return [void]
|
|
38
|
+
# @raise [Dis::Errors::NotFoundError] if the data is not found
|
|
39
|
+
#
|
|
40
|
+
# @example
|
|
41
|
+
# send_dis_data(document, disposition: "inline")
|
|
42
|
+
def send_dis_data(record, filename: nil, content_type: nil,
|
|
43
|
+
disposition: "attachment", status: 200)
|
|
44
|
+
file = record.open_data
|
|
45
|
+
send_file_headers!(
|
|
46
|
+
{ filename: filename || dis_metadata(record, :filename),
|
|
47
|
+
type: content_type || dis_metadata(record, :content_type),
|
|
48
|
+
disposition: }.compact
|
|
49
|
+
)
|
|
50
|
+
self.status = status
|
|
51
|
+
response.headers["Content-Length"] = file.size.to_s
|
|
52
|
+
self.response_body = Dis::ResponseBody.new(file)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def dis_metadata(record, name)
|
|
56
|
+
attribute = record.class.dis_attributes[name]
|
|
57
|
+
record[attribute] if attribute
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Dis
|
|
4
|
+
# = Dis Response Body
|
|
5
|
+
#
|
|
6
|
+
# Rack body that streams an open file and closes it once the
|
|
7
|
+
# response has been sent. The file may already be unlinked, so it is
|
|
8
|
+
# read through the open descriptor and never by path.
|
|
9
|
+
class ResponseBody
|
|
10
|
+
CHUNK_SIZE = 16_384
|
|
11
|
+
|
|
12
|
+
delegate :closed?, to: :@file
|
|
13
|
+
|
|
14
|
+
# @param file [File] an open, readable file
|
|
15
|
+
def initialize(file)
|
|
16
|
+
@file = file
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Returns the entire contents as a binary string.
|
|
20
|
+
#
|
|
21
|
+
# @return [String]
|
|
22
|
+
def body
|
|
23
|
+
@file.rewind
|
|
24
|
+
@file.read
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Yields the contents in chunks.
|
|
28
|
+
#
|
|
29
|
+
# @yieldparam chunk [String] a chunk of the contents
|
|
30
|
+
# @return [void]
|
|
31
|
+
def each
|
|
32
|
+
@file.rewind
|
|
33
|
+
while (chunk = @file.read(CHUNK_SIZE))
|
|
34
|
+
yield chunk
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Closes the underlying file.
|
|
39
|
+
#
|
|
40
|
+
# @return [void]
|
|
41
|
+
def close
|
|
42
|
+
@file.close unless @file.closed?
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
data/lib/dis/version.rb
CHANGED
data/lib/dis.rb
CHANGED
|
@@ -6,6 +6,7 @@ require "fog/core"
|
|
|
6
6
|
require "fog/local"
|
|
7
7
|
require "active_job"
|
|
8
8
|
require "concurrent"
|
|
9
|
+
require "dis/controller"
|
|
9
10
|
require "dis/engine"
|
|
10
11
|
require "dis/errors"
|
|
11
12
|
require "dis/jobs"
|
|
@@ -13,6 +14,7 @@ require "dis/logging"
|
|
|
13
14
|
require "dis/layer"
|
|
14
15
|
require "dis/layers"
|
|
15
16
|
require "dis/model"
|
|
17
|
+
require "dis/response_body"
|
|
16
18
|
require "dis/storage"
|
|
17
19
|
require "dis/validations"
|
|
18
20
|
|
|
@@ -27,6 +29,7 @@ require "dis/validations"
|
|
|
27
29
|
# configure layers via {Dis::Storage.layers}.
|
|
28
30
|
#
|
|
29
31
|
# @see Dis::Model
|
|
32
|
+
# @see Dis::Controller
|
|
30
33
|
# @see Dis::Storage
|
|
31
34
|
# @see Dis::Layer
|
|
32
35
|
module Dis
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: dis
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 2.1.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Inge Jørgensen
|
|
@@ -110,6 +110,7 @@ files:
|
|
|
110
110
|
- LICENSE
|
|
111
111
|
- README.md
|
|
112
112
|
- lib/dis.rb
|
|
113
|
+
- lib/dis/controller.rb
|
|
113
114
|
- lib/dis/engine.rb
|
|
114
115
|
- lib/dis/errors.rb
|
|
115
116
|
- lib/dis/jobs.rb
|
|
@@ -123,6 +124,7 @@ files:
|
|
|
123
124
|
- lib/dis/model.rb
|
|
124
125
|
- lib/dis/model/class_methods.rb
|
|
125
126
|
- lib/dis/model/data.rb
|
|
127
|
+
- lib/dis/response_body.rb
|
|
126
128
|
- lib/dis/storage.rb
|
|
127
129
|
- lib/dis/validations.rb
|
|
128
130
|
- lib/dis/validations/data_presence.rb
|
|
@@ -150,7 +152,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
150
152
|
- !ruby/object:Gem::Version
|
|
151
153
|
version: '0'
|
|
152
154
|
requirements: []
|
|
153
|
-
rubygems_version: 4.0.
|
|
155
|
+
rubygems_version: 4.0.16
|
|
154
156
|
specification_version: 4
|
|
155
157
|
summary: A file store for your Rails app
|
|
156
158
|
test_files: []
|