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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 341dc80b5a083c46a37da69c79e4ba9dd6061039
4
- data.tar.gz: 08b2b167f82bcc09f66c5c6424afd64f659a1aa8
2
+ SHA256:
3
+ metadata.gz: 5cb8a9f8a44513293da86ca083dd5d21387f2369517da289682e0195f1ec2ad7
4
+ data.tar.gz: fd15cbc2724c0125dc90070d90b4c25097e801e73224e446eeece2f07593c46e
5
5
  SHA512:
6
- metadata.gz: 382d0edf787592cbfe10e080173ab5018d8f7cef98e3bf8747cd4405de646edb1a8f0801aab19cc3e5c46d6706b69c56faf8dc16bfbaf69417f5bf342fa72cf4
7
- data.tar.gz: fc2749ccc2ad04800bf415a6b320ece8419b2d1f7ed04fdaeac8e6d3073f515d635fbfc0aa37396aa7bfb482f83fa387cb49fd4507aad0f4c6aea26ba3ce4630
6
+ metadata.gz: f07494205851ecaa4c0a9217c6721f42d04d4df8441da20bf3582f9f107dc35e5bd1b80220536147088e0387ccc265780a8ade62dbee42aad33c87d2d5d3e8e7
7
+ data.tar.gz: e06b2a61f8c282c34540f47d5aeaa2ce04293994aa19b0263940b40cfb203316a6d61d8a888faf246b3859c1f9257239273c1e65d34a8a567077e6d23048f7d5
data/README.md CHANGED
@@ -1,29 +1,45 @@
1
- # Dis [![Build Status](https://travis-ci.org/elektronaut/dis.svg?branch=master)](https://travis-ci.org/elektronaut/dis) [![Code Climate](https://codeclimate.com/github/elektronaut/dis/badges/gpa.svg)](https://codeclimate.com/github/elektronaut/dis) [![Code Climate](https://codeclimate.com/github/elektronaut/dis/badges/coverage.svg)](https://codeclimate.com/github/elektronaut/dis) [![Dependency Status](https://gemnasium.com/elektronaut/dis.svg)](https://gemnasium.com/elektronaut/dis)
1
+ [![Version](https://img.shields.io/gem/v/dis.svg?style=flat)](https://rubygems.org/gems/dis)
2
+ [![Build Status](https://travis-ci.org/elektronaut/dis.svg?branch=master)](https://travis-ci.org/elektronaut/dis)
3
+ [![Code Climate](https://codeclimate.com/github/elektronaut/dis/badges/gpa.svg)](https://codeclimate.com/github/elektronaut/dis)
4
+ [![Code Climate](https://codeclimate.com/github/elektronaut/dis/badges/coverage.svg)](https://codeclimate.com/github/elektronaut/dis)
5
+ [![Inline docs](http://inch-ci.org/github/elektronaut/dis.svg)](http://inch-ci.org/github/elektronaut/dis)
6
+ [![Security](https://hakiri.io/github/elektronaut/dis/master.svg)](https://hakiri.io/github/elektronaut/dis/master)
2
7
 
3
- Dis handles file uploads for your Rails app.
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
- Your files are stored in one or more layers, either on disk or in
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
- Files are indexed by the SHA1 hash of their contents. This means you get
14
- deduplication for free. This also means you run the (very slight) risk of
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 does not do any processing. The idea is to provide a simple foundation
19
- other gems can build on. If you are looking to handle uploaded images,
20
- check out [DynamicImage](https://github.com/elektronaut/dynamic_image).
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+ and Ruby 1.9.3+.
20
+ Requires Rails 4.2+.
23
21
 
24
- ## Documentation
22
+ ## Layers
25
23
 
26
- [Documentation on RubyDoc.info](http://rdoc.info/gems/dis)
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 are expected to use the Rails validators.
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 assign the data directly.
98
+ You can also pass a file directly:
74
99
 
75
100
  ```ruby
76
- Document.create(
77
- data: File.open('document.pdf'),
78
- content_type: 'application/pdf',
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
- ## Defining layers
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
- require 'fog/aws/storage'
109
+ Document.create(data: 'foo', content_type: 'text/plain', filename: 'foo.txt')
94
110
  ```
95
111
 
96
- Having a local layer first is a good idea, this will provide you
97
- with a cache on disk. Any misses will be filled from the next layer.
98
-
99
- ```ruby
100
- Dis::Storage.layers << Dis::Layer.new(
101
- Fog::Storage.new({provider: 'Local', local_root: Rails.root.join('db', 'binaries')}),
102
- path: Rails.env
103
- )
104
- ```
105
-
106
- Delayed layers will be processed out of the request cycle using
107
- whatever adapter you've configured
108
- [Active Job](https://github.com/rails/activejob) to use.
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
- ## Interacting with the store
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("stuff", file) # => "8843d7f92416211de9ebb963ff4ce28125932878"
145
- Dis::Storage.exists?("stuff", hash) # => true
146
- Dis::Storage.get("stuff", hash).body # => "foobar"
147
- Dis::Storage.delete("stuff", hash) # => true
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
@@ -2,3 +2,4 @@
2
2
 
3
3
  require 'dis/jobs/delete'
4
4
  require 'dis/jobs/store'
5
+ require 'dis/jobs/change_type'
@@ -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
@@ -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
  #
@@ -1,5 +1,5 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  module Dis
4
- VERSION = '1.1.1'.freeze
4
+ VERSION = '1.1.2'.freeze
5
5
  end
@@ -17,5 +17,6 @@ Dis::Storage.layers << Dis::Layer.new(
17
17
  # aws_secret_access_key: AWS_SECRET_ACCESS_KEY
18
18
  # }),
19
19
  # path: "my_bucket",
20
- # delayed: true
20
+ # delayed: true,
21
+ # readonly: false
21
22
  # )
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.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: 2017-08-02 00:00:00.000000000 Z
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.1
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.1
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
- rubyforge_project:
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
@@ -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.