dis 1.1.1 → 1.1.2

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