dis 1.1.1 → 1.1.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 +5 -5
- data/README.md +69 -79
- data/lib/dis/jobs.rb +1 -0
- data/lib/dis/jobs/change_type.rb +19 -0
- data/lib/dis/storage.rb +17 -0
- data/lib/dis/version.rb +1 -1
- data/lib/rails/generators/dis/install/templates/initializer.rb +2 -1
- metadata +6 -7
- data/MIT-LICENSE +0 -20
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 5cb8a9f8a44513293da86ca083dd5d21387f2369517da289682e0195f1ec2ad7
|
4
|
+
data.tar.gz: fd15cbc2724c0125dc90070d90b4c25097e801e73224e446eeece2f07593c46e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f07494205851ecaa4c0a9217c6721f42d04d4df8441da20bf3582f9f107dc35e5bd1b80220536147088e0387ccc265780a8ade62dbee42aad33c87d2d5d3e8e7
|
7
|
+
data.tar.gz: e06b2a61f8c282c34540f47d5aeaa2ce04293994aa19b0263940b40cfb203316a6d61d8a888faf246b3859c1f9257239273c1e65d34a8a567077e6d23048f7d5
|
data/README.md
CHANGED
@@ -1,29 +1,45 @@
|
|
1
|
-
|
1
|
+
[](https://rubygems.org/gems/dis)
|
2
|
+
[](https://travis-ci.org/elektronaut/dis)
|
3
|
+
[](https://codeclimate.com/github/elektronaut/dis)
|
4
|
+
[](https://codeclimate.com/github/elektronaut/dis)
|
5
|
+
[](http://inch-ci.org/github/elektronaut/dis)
|
6
|
+
[](https://hakiri.io/github/elektronaut/dis/master)
|
2
7
|
|
3
|
-
Dis
|
4
|
-
It's similar to [Paperclip](https://github.com/thoughtbot/paperclip)
|
5
|
-
and [Carrierwave](https://github.com/carrierwaveuploader/carrierwave),
|
6
|
-
but different in a few ways. Chiefly, it's much, much simpler.
|
8
|
+
# Dis
|
7
9
|
|
8
|
-
|
9
|
-
a cloud somewhere. [Fog](http://fog.io) and
|
10
|
-
[Active Job](https://github.com/rails/activejob) does most of the
|
11
|
-
heavy lifting.
|
10
|
+
Dis is a content-adressable store for file uploads in your Rails app.
|
12
11
|
|
13
|
-
|
14
|
-
|
15
|
-
hash collisions. There is no concept of updates in the data store,
|
16
|
-
a file with changed content is by definition a different file.
|
12
|
+
Data can be stored either on disk or in the cloud - anywhere that
|
13
|
+
[Fog](http://fog.io) knows how to talk to.
|
17
14
|
|
18
|
-
It
|
19
|
-
|
20
|
-
|
15
|
+
It doesn't do any processing, but it's a simple foundation to roll
|
16
|
+
your own on. If you're looking to handle image uploads, check out
|
17
|
+
[DynamicImage](https://github.com/elektronaut/dynamic_image). It's
|
18
|
+
built on top of Dis and handles resizing, cropping and more on demand.
|
21
19
|
|
22
|
-
Requires Rails 4.2
|
20
|
+
Requires Rails 4.2+.
|
23
21
|
|
24
|
-
##
|
22
|
+
## Layers
|
25
23
|
|
26
|
-
|
24
|
+
The underlaying storage consists of one or more layers. A layer is a
|
25
|
+
unit of storage location, which can either be a local path, or a cloud
|
26
|
+
provider like Amazon S3 or Google Cloud Storage.
|
27
|
+
|
28
|
+
There are two types of layers, immediate and delayed. Files are
|
29
|
+
written to immediate layers and then replicated to the rest in the
|
30
|
+
background using ActiveJob.
|
31
|
+
|
32
|
+
Reads are performed from the first available layer. In case of a read
|
33
|
+
miss, the file is backfilled from the next layer.
|
34
|
+
|
35
|
+
An example configuration could be to have a local layer first, and
|
36
|
+
then for example an Amazon S3 bucket. This provides you with an
|
37
|
+
on-disk cache backed by cloud storage. You can also add additional
|
38
|
+
layers if you want fault tolerance across regions or even providers.
|
39
|
+
|
40
|
+
Layers can be configured as read-only. This can be useful if you want
|
41
|
+
to read from your staging or production environment while developing
|
42
|
+
locally, or if you're transitioning away from a provider.
|
27
43
|
|
28
44
|
## Installation
|
29
45
|
|
@@ -39,6 +55,15 @@ Now, run the generator to install the initializer:
|
|
39
55
|
bin/rails generate dis:install
|
40
56
|
```
|
41
57
|
|
58
|
+
By default, files will be stored in `db/dis`. You can edit
|
59
|
+
`config/initializers/dis.rb` if you want to change the path or add
|
60
|
+
additional layers. Note that you also need the corresponding
|
61
|
+
[Fog gem](https://github.com/fog) if you want to use cloud storage:
|
62
|
+
|
63
|
+
```ruby
|
64
|
+
gem "fog-aws"
|
65
|
+
```
|
66
|
+
|
42
67
|
## Usage
|
43
68
|
|
44
69
|
Run the generator to create your model.
|
@@ -50,7 +75,7 @@ bin/rails generate dis:model Document
|
|
50
75
|
This will create a model along with a migration.
|
51
76
|
|
52
77
|
Here's what your model might look like. Note that Dis does not
|
53
|
-
validate any data by default, you
|
78
|
+
validate any data by default, but you can use the standard Rails validators.
|
54
79
|
A validator for validating presence of data is provided.
|
55
80
|
|
56
81
|
```ruby
|
@@ -70,81 +95,46 @@ document_params = params.require(:document).permit(:file)
|
|
70
95
|
@document = Document.create(document_params)
|
71
96
|
```
|
72
97
|
|
73
|
-
You can also
|
98
|
+
You can also pass a file directly:
|
74
99
|
|
75
100
|
```ruby
|
76
|
-
Document.create(
|
77
|
-
|
78
|
-
|
79
|
-
filename: 'document.pdf'
|
80
|
-
)
|
101
|
+
Document.create(data: File.open('document.pdf'),
|
102
|
+
content_type: 'application/pdf',
|
103
|
+
filename: 'document.pdf')
|
81
104
|
```
|
82
105
|
|
83
|
-
|
84
|
-
|
85
|
-
The install generator will set you up with a local storage layer on disk,
|
86
|
-
but this is configurable in `config/initializers/dis.rb`.
|
87
|
-
|
88
|
-
You can have as many layers as you want, any storage provider
|
89
|
-
[supported by Fog](http://fog.io/storage/) should work in theory. Only the
|
90
|
-
local storage is loaded by default, you'll have to manually require your provider.
|
106
|
+
..or even a string:
|
91
107
|
|
92
108
|
```ruby
|
93
|
-
|
109
|
+
Document.create(data: 'foo', content_type: 'text/plain', filename: 'foo.txt')
|
94
110
|
```
|
95
111
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
Note: You must have at least one non-delayed layer.
|
110
|
-
|
111
|
-
```ruby
|
112
|
-
if Rails.env.production?
|
113
|
-
Dis::Storage.layers << Dis::Layer.new(
|
114
|
-
Fog::Storage.new({
|
115
|
-
provider: 'AWS',
|
116
|
-
aws_access_key_id: YOUR_AWS_ACCESS_KEY_ID,
|
117
|
-
aws_secret_access_key: YOUR_AWS_SECRET_ACCESS_KEY
|
118
|
-
}),
|
119
|
-
path: "my_bucket",
|
120
|
-
delayed: true
|
121
|
-
)
|
122
|
-
end
|
123
|
-
```
|
124
|
-
|
125
|
-
You can also set layers to be read only. This is handy if you want to
|
126
|
-
access production data from your development environment, or if you
|
127
|
-
are in the process of migration from one provider to another.
|
128
|
-
|
129
|
-
```ruby
|
130
|
-
if Rails.env.development?
|
131
|
-
Dis::Storage.layers << Dis::Layer.new(
|
132
|
-
Fog::Storage.new(...),
|
133
|
-
readonly: true
|
134
|
-
)
|
112
|
+
Getting your file back out is straightforward:
|
113
|
+
|
114
|
+
``` ruby
|
115
|
+
class DocumentsController < ApplicationController
|
116
|
+
def show
|
117
|
+
@document = Document.find(params[:id])
|
118
|
+
if stale?(@document)
|
119
|
+
send_data(@document.data,
|
120
|
+
filename: @document.filename,
|
121
|
+
type: @document.content_type,
|
122
|
+
disposition: "attachment)
|
123
|
+
end
|
124
|
+
end
|
135
125
|
end
|
136
126
|
```
|
137
127
|
|
138
|
-
##
|
128
|
+
## Behind the scenes
|
139
129
|
|
140
130
|
You can interact directly with the store if you want.
|
141
131
|
|
142
132
|
```ruby
|
143
133
|
file = File.open("foo.txt")
|
144
|
-
hash = Dis::Storage.store("
|
145
|
-
Dis::Storage.exists?("
|
146
|
-
Dis::Storage.get("
|
147
|
-
Dis::Storage.delete("
|
134
|
+
hash = Dis::Storage.store("documents", file) # => "8843d7f92416211de9ebb963ff4ce28125932878"
|
135
|
+
Dis::Storage.exists?("documents", hash) # => true
|
136
|
+
Dis::Storage.get("documents", hash).body # => "foobar"
|
137
|
+
Dis::Storage.delete("documents", hash) # => true
|
148
138
|
```
|
149
139
|
|
150
140
|
## License
|
data/lib/dis/jobs.rb
CHANGED
@@ -0,0 +1,19 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Dis
|
4
|
+
module Jobs
|
5
|
+
# = Dis ChangeType Job
|
6
|
+
#
|
7
|
+
# Handles delayed object type change.
|
8
|
+
#
|
9
|
+
# Dis::Jobs::ChangeType.perform_later("old_things", "new_things", hash)
|
10
|
+
class ChangeType < ActiveJob::Base
|
11
|
+
queue_as :dis
|
12
|
+
|
13
|
+
def perform(prev_type, new_type, hash)
|
14
|
+
Dis::Storage.delayed_store(new_type, hash)
|
15
|
+
Dis::Storage.delayed_delete(prev_type, hash)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/dis/storage.rb
CHANGED
@@ -38,6 +38,23 @@ module Dis
|
|
38
38
|
@layers ||= Dis::Layers.new
|
39
39
|
end
|
40
40
|
|
41
|
+
# Changes the type of an object. Kicks off a
|
42
|
+
# <tt>Dis::Jobs::ChangeType</tt> job if any delayed layers are defined.
|
43
|
+
#
|
44
|
+
# Dis::Storage.change_type("old_things", "new_things", hash)
|
45
|
+
def change_type(prev_type, new_type, hash)
|
46
|
+
require_writeable_layers!
|
47
|
+
file = get(prev_type, hash)
|
48
|
+
store_immediately!(new_type, file)
|
49
|
+
layers.immediate.writeable.each do |layer|
|
50
|
+
layer.delete(prev_type, hash)
|
51
|
+
end
|
52
|
+
if layers.delayed.writeable.any?
|
53
|
+
Dis::Jobs::ChangeType.perform_later(prev_type, new_type, hash)
|
54
|
+
end
|
55
|
+
hash
|
56
|
+
end
|
57
|
+
|
41
58
|
# Stores a file and returns a digest. Kicks off a
|
42
59
|
# <tt>Dis::Jobs::Store</tt> job if any delayed layers are defined.
|
43
60
|
#
|
data/lib/dis/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dis
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
4
|
+
version: 1.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Inge Jørgensen
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-02-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -86,14 +86,14 @@ dependencies:
|
|
86
86
|
requirements:
|
87
87
|
- - "~>"
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version: 3.5
|
89
|
+
version: '3.5'
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
94
|
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
|
-
version: 3.5
|
96
|
+
version: '3.5'
|
97
97
|
description: Dis is a Rails plugin that stores your file uploads and other binary
|
98
98
|
blobs.
|
99
99
|
email:
|
@@ -102,12 +102,12 @@ executables: []
|
|
102
102
|
extensions: []
|
103
103
|
extra_rdoc_files: []
|
104
104
|
files:
|
105
|
-
- MIT-LICENSE
|
106
105
|
- README.md
|
107
106
|
- lib/dis.rb
|
108
107
|
- lib/dis/engine.rb
|
109
108
|
- lib/dis/errors.rb
|
110
109
|
- lib/dis/jobs.rb
|
110
|
+
- lib/dis/jobs/change_type.rb
|
111
111
|
- lib/dis/jobs/delete.rb
|
112
112
|
- lib/dis/jobs/store.rb
|
113
113
|
- lib/dis/layer.rb
|
@@ -142,8 +142,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
142
142
|
- !ruby/object:Gem::Version
|
143
143
|
version: '0'
|
144
144
|
requirements: []
|
145
|
-
|
146
|
-
rubygems_version: 2.5.1
|
145
|
+
rubygems_version: 3.0.1
|
147
146
|
signing_key:
|
148
147
|
specification_version: 4
|
149
148
|
summary: A file store for your Rails app
|
data/MIT-LICENSE
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
Copyright 2014 Inge Jørgensen
|
2
|
-
|
3
|
-
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
-
a copy of this software and associated documentation files (the
|
5
|
-
"Software"), to deal in the Software without restriction, including
|
6
|
-
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
-
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
-
permit persons to whom the Software is furnished to do so, subject to
|
9
|
-
the following conditions:
|
10
|
-
|
11
|
-
The above copyright notice and this permission notice shall be
|
12
|
-
included in all copies or substantial portions of the Software.
|
13
|
-
|
14
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
-
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
-
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
-
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
-
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
-
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
-
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|