shrine 0.9.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of shrine might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 21c82440698540e29ee787915b4bbdf9c3289f72
4
- data.tar.gz: 70e3d33cd286ed3911df5d130b3f72f67c16e571
3
+ metadata.gz: 583eed751bfa6c1ae0ad5d9495509091563a8c02
4
+ data.tar.gz: 9c82a62a10a45df20f3f4d9422066beb705cfa39
5
5
  SHA512:
6
- metadata.gz: 349f0b0bfd9c3f96e752a99e1e126c15adac5071130a0804407bd6990d76a831cb68ea86f8dd72888cf04891b4623cf61d0bd4ec5ce5eaf9e1401cea1c7c4c72
7
- data.tar.gz: 2ba7dca90b8e1730a8fa2d303ad2750bd2d96c0d5cf52770486c912b85c63ff0c04ec4c60c48ad780a97ff5711b1da5a24d7ad9e28e381decd24b546c66ebbbd
6
+ metadata.gz: 68e093c6b118b379383305bfede12fd5710342c82c6b66040661be744d6995a723147f3b426b0d8afc03009c35d3b21a529232822e9232d2c25531d831fd973b
7
+ data.tar.gz: 41fabbd7fa515c3eb992bbbf5205fd924d502c64ec6f430d053ef135512e2476797435a5a4642fd066ea9bd8ba0b375455317a6bc54aaabcf24b557841b98de1
data/README.md CHANGED
@@ -2,12 +2,15 @@
2
2
 
3
3
  Shrine is a toolkit for file uploads in Ruby applications.
4
4
 
5
+ If you're new, you're encouraged to read the [introductory blog post] which
6
+ explains the motivation behind Shrine.
7
+
5
8
  ## Resources
6
9
 
7
10
  * Documentation: [shrinerb.com](http://shrinerb.com)
8
11
  * Source: [github.com/janko-m/shrine](https://github.com/janko-m/shrine)
9
12
  * Bugs: [github.com/janko-m/shrine/issues](https://github.com/janko-m/shrine/issues)
10
- * Discussion: [groups.google.com/group/ruby-shrine](https://groups.google.com/forum/#!forum/ruby-shrine)
13
+ * Help & Dicussion: [groups.google.com/group/ruby-shrine](https://groups.google.com/forum/#!forum/ruby-shrine)
11
14
 
12
15
  ## Installation
13
16
 
@@ -15,7 +18,7 @@ Shrine is a toolkit for file uploads in Ruby applications.
15
18
  gem "shrine"
16
19
  ```
17
20
 
18
- Shrine has been tested on MRI 2.1, MRI 2.2 and JRuby.
21
+ Shrine has been tested on MRI 2.1, MRI 2.2, JRuby and Rubinius.
19
22
 
20
23
  ## Basics
21
24
 
@@ -31,7 +34,7 @@ uploader = Shrine.new(:file_system)
31
34
 
32
35
  uploaded_file = uploader.upload(File.open("avatar.jpg"))
33
36
  uploaded_file #=> #<Shrine::UploadedFile>
34
- uploaded_file.url #=> "uploads/9260ea09d8effd.jpg"
37
+ uploaded_file.url #=> "/uploads/9260ea09d8effd.jpg"
35
38
  uploaded_file.data #=>
36
39
  # {
37
40
  # "storage" => "file_system",
@@ -55,32 +58,39 @@ to be an actual IO, it's enough that it responds to these 5 methods:
55
58
  `#read(*args)`, `#size`, `#eof?`, `#rewind` and `#close`.
56
59
  `ActionDispatch::Http::UploadedFile` is one such object.
57
60
 
58
- Now that we've uploaded the file to the underlying storage, we can download it:
61
+ The returned `Shrine::UploadedFile` represents the file that has been uploaded,
62
+ and we can do a lot with it:
59
63
 
60
64
  ```rb
61
- file = uploaded_file.download
62
- file #=> #<Tempfile:/var/folders/k7/6zx6dx6x7ys3rv3srh0nyfj00000gn/T/20151004-74201-1t2jacf>
65
+ uploaded_file.url #=> "/uploads/938kjsdf932.jpg"
66
+ uploaded_file.read #=> "..."
67
+ uploaded_file.exists? #=> true
68
+ uploaded_file.download #=> #<Tempfile:/var/folders/k7/6zx6dx6x7ys3rv3srh0nyfj00000gn/T/20151004-74201-1t2jacf>
69
+ uploaded_file.metadata #=> {...}
63
70
  ```
64
71
 
65
- When we're done, we can delete the file:
72
+ To read about the metadata that is stored with the uploaded file, see the
73
+ [metadata](#metadata) section. Once you're done with the file, you can delete
74
+ it.
66
75
 
67
76
  ```rb
68
- uploader.delete(uploaded_file)
69
- uploaded_file.exists? #=> false
77
+ uploaded_file.delete
70
78
  ```
71
79
 
72
80
  ## Attachment
73
81
 
74
- In web applications, instead of managing files directly, we want to treat them
75
- as "attachments" to models and to tie them to the lifecycle of records. Shrine
76
- does this by generating and including "attachment" modules.
82
+ In web applications, instead of managing files directly, we rather want to
83
+ treat them as "attachments" to models and to tie them to the lifecycle of
84
+ records. In Shrine we do this by generating and including "attachment" modules.
77
85
 
78
86
  Firstly we need to assign the special `:cache` and `:store` storages:
79
87
 
80
88
  ```rb
89
+ require "shrine/storage/file_system"
90
+
81
91
  Shrine.storages = {
82
- cache: Shrine::Storage::FileSystem.new(Dir.tmpdir),
83
- store: Shrine::Storage::FileSystem.new("public", subdirectory: "uploads"),
92
+ cache: Shrine::Storage::FileSystem.new("public", subdirectory: "uploads/cache"),
93
+ store: Shrine::Storage::FileSystem.new("public", subdirectory: "uploads/store"),
84
94
  }
85
95
  ```
86
96
 
@@ -89,7 +99,7 @@ uploading:
89
99
 
90
100
  ```rb
91
101
  class ImageUploader < Shrine
92
- # here goes your uploading logic
102
+ # logic for uploading images
93
103
  end
94
104
  ```
95
105
 
@@ -111,12 +121,7 @@ user = User.new
111
121
  user.avatar = File.open("avatar.jpg") # uploads the file to `:cache`
112
122
  user.avatar #=> #<Shrine::UploadedFile>
113
123
  user.avatar_url #=> "/uploads/9260ea09d8effd.jpg"
114
- user.avatar_data #=>
115
- # {
116
- # "storage" => "cache",
117
- # "id" => "9260ea09d8effd.jpg",
118
- # "metadata" => {...},
119
- # }
124
+ user.avatar_data #=> "{\"storage\":\"cache\",\"id\":\"9260ea09d8effd.jpg\",\"metadata\":{...}}"
120
125
  ```
121
126
 
122
127
  The attachment module has added `#avatar`, `#avatar=` and `#avatar_url`
@@ -124,11 +129,11 @@ methods to our User. This is what's happening:
124
129
 
125
130
  ```rb
126
131
  Shrine[:avatar] #=> #<Shrine::Attachment(avatar)>
127
- Shrine[:avatar].class #=> Module
128
- Shrine[:avatar].instance_methods #=> [:avatar=, :avatar, :avatar_url, ...]
132
+ Shrine[:avatar].is_a?(Module) #=> true
133
+ Shrine[:avatar].instance_methods #=> [:avatar=, :avatar, :avatar_url, :avatar_attacher]
129
134
 
130
135
  Shrine[:document] #=> #<Shrine::Attachment(document)>
131
- Shrine[:document].instance_methods #=> [:document=, :document, :document_url, ...]
136
+ Shrine[:document].instance_methods #=> [:document=, :document, :document_url, :document_attacher]
132
137
 
133
138
  # If you prefer to be more explicit, you can use the expanded forms
134
139
  Shrine.attachment(:avatar)
@@ -147,7 +152,7 @@ Sequel and ActiveRecord ORMs. Shrine uses the "\<attachment\>\_data" column
147
152
  for storing attachments, so you'll need to add it in a migration:
148
153
 
149
154
  ```rb
150
- add_column :users, :avatar_data, :text
155
+ add_column :users, :avatar_data, :text # or a "jsonb" column if you need querying
151
156
  ```
152
157
  ```rb
153
158
  Shrine.plugin :sequel
@@ -188,7 +193,7 @@ Shrine comes with a `direct_upload` plugin which provides an endpoint
188
193
  (implemented in [Roda]) that can be used for AJAX uploads.
189
194
 
190
195
  ```rb
191
- Shrine.plugin :direct_upload # Exposes a Roda endpoint
196
+ Shrine.plugin :direct_upload # Provides a Roda endpoint
192
197
  ```
193
198
  ```rb
194
199
  Rails.application.routes.draw do
@@ -196,9 +201,17 @@ Rails.application.routes.draw do
196
201
  mount ImageUploader.direct_endpoint => "/attachments/images"
197
202
  end
198
203
  ```
199
- ```sh
200
- $ curl -F "file=@/path/to/avatar.jpg" localhost:3000/attachments/images/cache/avatar
201
- # {"id":"43kewit94.jpg","storage":"cache","metadata":{...}}
204
+ ```rb
205
+ # POST /attachments/images/cache/avatar
206
+ {
207
+ "id": "43kewit94.jpg",
208
+ "storage": "cache",
209
+ "metadata": {
210
+ "size": 384393,
211
+ "filename": "nature.jpg",
212
+ "mime_type": "image/jpeg"
213
+ }
214
+ }
202
215
  ```
203
216
 
204
217
  There are many great JavaScript libraries for AJAX file uploads, for example
@@ -212,8 +225,10 @@ $('[type="file"]').fileupload({
212
225
  });
213
226
  ```
214
227
 
215
- This plugin also provides a route for direct S3 uploads. See the [example app]
216
- for how you can do multiple uploads directly to S3.
228
+ This is an oversimplified implementation without any UX, it's just to show you
229
+ how easy it is. The `direct_upload` plugin also provides a route for direct S3
230
+ uploads, see the [example app] for how you can do multiple uploads directly to
231
+ S3.
217
232
 
218
233
  ## Processing
219
234
 
@@ -237,9 +252,9 @@ assigned and saved, an "upload" actually happens two times. First the file is
237
252
  `:store` on save.
238
253
 
239
254
  Ok, now how do we do the actual processing? Well, Shrine actually doesn't ship
240
- with any image processing functionality, because that is a generic problem that
241
- belongs in a separate gem. So, I created the [image_processing] gem which you
242
- can use with Shrine:
255
+ with any file processing functionality, because that is a generic problem that
256
+ belongs in a separate gem. If the type of files you're uploading are images, I
257
+ created the [image_processing] gem which you can use with Shrine:
243
258
 
244
259
  ```rb
245
260
  require "image_processing/mini_magick"
@@ -249,7 +264,7 @@ class ImageUploader < Shrine
249
264
 
250
265
  def process(io, context)
251
266
  if context[:phase] == :store
252
- process_to_limit!(io.download, 700, 700)
267
+ resize_to_limit(io.download, 700, 700)
253
268
  end
254
269
  end
255
270
  end
@@ -266,9 +281,9 @@ storing the original file.
266
281
 
267
282
  ### Versions
268
283
 
269
- Often you'll want to store various thumbnails alongside your original image.
270
- For that you just need to load the `versions` plugin, and now in `#process`
271
- you can return a Hash of versions:
284
+ If you're uploading images, often you'll want to store various thumbnails
285
+ alongside your original image. For that you just need to load the `versions`
286
+ plugin, and now in `#process` you can return a Hash of versions:
272
287
 
273
288
  ```rb
274
289
  require "image_processing/mini_magick"
@@ -279,9 +294,9 @@ class ImageUploader < Shrine
279
294
 
280
295
  def process(io, context)
281
296
  if context[:phase] == :store
282
- size_700 = process_to_limit!(io.download, 700, 700)
283
- size_500 = process_to_limit!(size_700, 500, 500)
284
- size_300 = process_to_limit!(size_500, 300, 300)
297
+ size_700 = resize_to_limit(io.download, 700, 700)
298
+ size_500 = resize_to_limit(size_700, 500, 500)
299
+ size_300 = resize_to_limit(size_500, 300, 300)
285
300
 
286
301
  {large: size_700, medium: size_500, small: size_300}
287
302
  end
@@ -299,12 +314,6 @@ Now when you access the stored attachment, a Hash of versions will be returned
299
314
  instead:
300
315
 
301
316
  ```rb
302
- user.avatar #=>
303
- # {
304
- # large: #<Shrine::UploadedFile>,
305
- # medium: #<Shrine::UploadedFile>,
306
- # small: #<Shrine::UploadedFile>,
307
- # }
308
317
  user.avatar.class #=> Hash
309
318
 
310
319
  # With the store_dimensions plugin
@@ -355,13 +364,14 @@ Validations are registered by calling `Shrine::Attacher.validate`, and are best
355
364
  done with the `validation_helpers` plugin:
356
365
 
357
366
  ```rb
358
- class ImageUploader < Shrine
367
+ class DocumentUploader < Shrine
359
368
  plugin :validation_helpers
360
369
 
361
370
  Attacher.validate do
362
371
  # Evaluated inside an instance of Shrine::Attacher.
363
372
  if record.guest?
364
- validate_max_size 2*1024*1024, message: "is too large (max is 2 MB)"
373
+ validate_max_size 10*1024*1024, message: "is too large (max is 10 MB)"
374
+ validate_mime_type_inclusion ["application/pdf"]
365
375
  end
366
376
  end
367
377
  end
@@ -369,9 +379,9 @@ end
369
379
 
370
380
  ```rb
371
381
  user = User.new
372
- user.avatar = File.open("big_image.jpg")
382
+ user.resume = File.open("resume.pdf")
373
383
  user.valid? #=> false
374
- user.errors.to_hash #=> {avatar: ["is too large (max is 2 MB)"]}
384
+ user.errors.to_hash #=> {resume: ["is too large (max is 2 MB)"]}
375
385
  ```
376
386
 
377
387
  ## Metadata
@@ -404,11 +414,11 @@ browser sets solely based on the extension of the uploaded file. This means
404
414
  that by default Shrine's "mime_type" is *not* guaranteed to hold the actual
405
415
  MIME type of the file.
406
416
 
407
- To help with that Shrine provides the `extract_mime_type` plugin, which by
408
- deafult uses the UNIX [file] utility to determine the actual MIME type:
417
+ To help with that Shrine provides the `determine_mime_type` plugin, which by
418
+ default uses the UNIX [file] utility to determine the actual MIME type:
409
419
 
410
420
  ```rb
411
- Shrine.plugin :extract_mime_type
421
+ Shrine.plugin :determine_mime_type
412
422
  ```
413
423
  ```rb
414
424
  user = User.create(avatar: File.open("image.mp4")) # image with a .mp4 extension
@@ -417,8 +427,8 @@ user.avatar.mime_type #=> "image/png"
417
427
 
418
428
  ### Dimensions
419
429
 
420
- Shrine ships with the `store_dimensions` plugin which extracts dimensions
421
- using the [fastimage] gem.
430
+ If you're uploading images and you want to store dimensions, you can use the
431
+ `store_dimensions` plugin which extracts dimensions using the [fastimage] gem.
422
432
 
423
433
  ```rb
424
434
  ImageUploader.plugin :store_dimensions
@@ -463,7 +473,7 @@ end
463
473
  ## Locations
464
474
 
465
475
  By default files will all be put in the same folder. If you want that each
466
- record has its own directory, you can use the `pretty_location` plugin:
476
+ attachment has its own directory, you can use the `pretty_location` plugin:
467
477
 
468
478
  ```rb
469
479
  Shrine.plugin :pretty_location
@@ -576,14 +586,14 @@ In combination with direct upload for caching, this provides a completely
576
586
  seamless user experience. First the user ansynchronosuly caches the file and
577
587
  hopefully sees a nice progress bar. After this is finishes and user submits the
578
588
  form, promoting will be kicked off into a background job, and the record will
579
- be saved with the cached image. If your cache is public (e.g. in the "public"
589
+ be saved with the cached file If your cache is public (e.g. in the "public"
580
590
  folder), the end user will immediately see their uploaded file, because the URL
581
591
  will point to the cached version.
582
592
 
583
593
  In the meanwhile, what `#promote` does is it uploads the cached file `:store`,
584
594
  and writes the stored file to the column. When the record gets saved, the URL
585
595
  will switch from filesystem to S3, but the user won't even notice that
586
- something happened, because they will still see the same image.
596
+ something happened, because they will still see the same file.
587
597
 
588
598
  ### Generality
589
599
 
@@ -661,3 +671,4 @@ The gem is available as open source under the terms of the [MIT License].
661
671
  [MIT License]: http://opensource.org/licenses/MIT
662
672
  [example app]: https://github.com/janko-m/shrine-example
663
673
  [ships with over 25 plugins]: http://shrinerb.com#plugins
674
+ [introductory blog post]: http://twin.github.io/introducing-shrine/
@@ -0,0 +1,436 @@
1
+ # Shrine for CarrierWave Users
2
+
3
+ This guide is aimed at helping CarrierWave users transition to Shrine. We will
4
+ first generally mention what are the key differences. Afterwards there is an
5
+ extensive reference of CarrierWave's interface and what is the equivalent in
6
+ Shrine.
7
+
8
+ ## Uploaders
9
+
10
+ Shrine has a concept of uploaders similar to CarrierWave's, but instead of
11
+ inheriting from `CarrierWave::Uploader::Base`, you inherit from `Shrine`
12
+ directly:
13
+
14
+ ```rb
15
+ class ImageUploader < Shrine
16
+ # ...
17
+ end
18
+ ```
19
+
20
+ While in CarrierWave you choose a storages for uploaders directly, in Shrine
21
+ you first register storages globally (under a symbol name), and then you
22
+ instantiate uploaders with a specific storage.
23
+
24
+ ```rb
25
+ require "shrine/storage/file_system"
26
+
27
+ Shrine.storages = {
28
+ cache: Shrine::Storage::FileSystem.new("public", subdirectory: "uploads/cache"),
29
+ store: Shrine::Storage::FileSystem.new("public", subdirectory: "uploads/store"),
30
+ }
31
+ ```
32
+ ```rb
33
+ cache_uploader = Shrine.new(:cache)
34
+ store_uploader = Shrine.new(:store)
35
+ ```
36
+
37
+ CarrierWave uses symbols for referencing storages (`:file`, `:fog`, ...), but
38
+ in Shrine you instantiate storages directly. This makes storages much more
39
+ flexible, because this way they can have their own options that are specific to
40
+ them.
41
+
42
+ ### Processing
43
+
44
+ In Shrine processing is done instance-level in the `#process` method. To
45
+ generate versions, you simply return a hash, and also load the `versions`
46
+ plugin to make your uploader recognize versions:
47
+
48
+ ```rb
49
+ require "image_processing/mini_magick" # part of the "image_processing" gem
50
+
51
+ class ImageUploader < Shrine
52
+ include ImageProcessing::MiniMagick
53
+ plugin :versions, names: [:small, :medium, :large]
54
+
55
+ def process(io, context)
56
+ if context[:phase] == :store
57
+ thumb = resize_to_limit(io.download, 300, 300)
58
+ {original: io, thumb: thumb}
59
+ end
60
+ end
61
+ end
62
+ ```
63
+
64
+ ## Attachments
65
+
66
+ Like CarrierWave, Shrine also provides integrations with ORMs, it ships with
67
+ plugins for both Sequel and ActiveRecord (but it can also be used with simple
68
+ PORO models).
69
+
70
+ ```rb
71
+ Shrine.plugin :sequel # If you're using Sequel
72
+ Shrine.plugin :activerecord # If you're using ActiveRecord
73
+ ```
74
+
75
+ Instead of giving you class methods for "mounting" uploaders, in Shrine you
76
+ generate "attachment modules" which you include in your models:
77
+
78
+ ```rb
79
+ class User < Sequel::Model
80
+ include ImageUploader[:avatar] # adds `avatar`, `avatar=` and `avatar_url` methods
81
+ end
82
+ ```
83
+
84
+ You models are required to have the `<attachment>_data` column, in the above
85
+ case `avatar_data`. It contains the storage and location of the file, as well
86
+ as additional metadata.
87
+
88
+ ### Multiple uploads
89
+
90
+ Shrine doesn't have support for multiple uploads like CarrierWave does, instead
91
+ it expects that you will implement multiple uploads yourself using a separate
92
+ model. This is a good thing, because the implementation is specific to the ORM
93
+ you're using, and it's analogous to how you would implement adding items to any
94
+ dynamic one-to-many relationship. Take a look at the [example app] which
95
+ demonstrates how easy it is to implement multiple uploads.
96
+
97
+ ## CarrierWave to Shrine direct mapping
98
+
99
+ ### `CarrierWave::Uploader::Base`
100
+
101
+ #### `.storage`
102
+
103
+ When using models, by default all storages use `:cache` for cache, and `:store`
104
+ for store. If you want to change that, you can use the `default_storage`
105
+ plugin:
106
+
107
+ ```rb
108
+ Shrine.storages[:dropbox] = Shrine::Storage::Dropbox.new(*args)
109
+ ```
110
+
111
+ ```rb
112
+ class ImageUploader
113
+ plugin :default_storage, store: :dropbox
114
+ end
115
+ ```
116
+
117
+ #### `.process`, `.version`
118
+
119
+ As explained in the "Processing" section, processing is done by overriding the
120
+ `Shrine#process` method.
121
+
122
+ #### `.before`, `.after`
123
+
124
+ In Shrine you can get callbacks by loading the `hooks` plugin. Unlike
125
+ CarrierWave, and much like Sequel, Shrine implements callbacks by overriding
126
+ instance methods:
127
+
128
+ ```rb
129
+ class ImageUploader < Shrine
130
+ plugin :hooks
131
+
132
+ def after_upload(io, context)
133
+ super
134
+ # do something
135
+ end
136
+ end
137
+ ```
138
+
139
+ #### `#store!`, `#cache!`
140
+
141
+ In Shrine you store and cache files by instantiating it with a corresponding
142
+ storage, and calling `#upload`:
143
+
144
+ ```rb
145
+ ImageUploader.new(:cache).upload(file)
146
+ ImageUploader.new(:store).upload(file)
147
+ ```
148
+
149
+ Note that in Shrine you cannot pass in a path to the file, you always have to
150
+ pass an IO-like object, which is required to respond to: `#read(*args)`,
151
+ `#size`, `#eof?`, `#rewind` and `#close`.
152
+
153
+ #### `#retrieve_from_store!` and `#retrieve_from_cache!`
154
+
155
+ In Shrine you simply call `#download` on the uploaded file:
156
+
157
+ ```rb
158
+ uploaded_file = ImageUploader.new(:store).upload(file)
159
+ uploaded_file.download #=> #<Tempfile>
160
+ ```
161
+
162
+ #### `#url`
163
+
164
+ In Shrine you call `#url` on uploaded files:
165
+
166
+ ```rb
167
+ user.avatar #=> #<Shrine::UploadedFile>
168
+ user.avatar.url #=> "/uploads/398454ujedfggf.jpg"
169
+ ```
170
+
171
+ #### `#identifier`
172
+
173
+ This method corresponds to `#original_filename` on the uploaded file:
174
+
175
+ ```rb
176
+ user.avatar #=> #<Shrine::UploadedFile>
177
+ user.avatar.original_filename #=> "avatar.jpg"
178
+ ```
179
+
180
+ #### `#store_dir`, `#cache_dir`
181
+
182
+ Shrine here provides a `#generate_location` method, which is triggered for all
183
+ storages:
184
+
185
+ ```rb
186
+ class ImageUploader < Shrine
187
+ def generate_location(io, context)
188
+ case storage_key
189
+ when :cache then "..."
190
+ when :store then "..."
191
+ end
192
+ end
193
+ end
194
+ ```
195
+
196
+ The `context` variable holds the additional data, like the attacment name and
197
+ the record instance. You might also want to use the `pretty_location` plugin
198
+ for automatically generating an organized folder structure.
199
+
200
+ #### `#default_url`
201
+
202
+ Similarly to CarrierWave, you also provide default URLs be overriding the
203
+ method:
204
+
205
+ ```rb
206
+ class ImageUploader < Shrine
207
+ def default_url(context)
208
+ # ...
209
+ end
210
+ end
211
+ ```
212
+
213
+ The `context` variable holds the name of the attachment, record instance and
214
+ in some cases the `:version`.
215
+
216
+ #### `#extension_white_list`, `#extension_black_list`
217
+
218
+ In Shrine extension whitelisting/blacklisting is a part of validations, and is
219
+ provided by the `validation_helpers` plugin:
220
+
221
+ ```rb
222
+ class ImageUploader < Shrine
223
+ plugin :validation_helpers
224
+
225
+ Attacher.validate do
226
+ validate_extension_inclusion [/jpe?g/, 'png'] # whitelist
227
+ validate_extension_exclusion ['php'] # blacklist
228
+ end
229
+ end
230
+ ```
231
+
232
+ #### `#blacklist_mime_type_pattern`, `#whitelist_mime_type_pattern`
233
+
234
+ In Shrine MIME type whitelisting/blacklisting is part of validations, and is
235
+ provided by the `validation_helpers` plugin:
236
+
237
+ ```rb
238
+ class ImageUploader < Shrine
239
+ plugin :validation_helpers
240
+
241
+ Attacher.validate do
242
+ validate_mime_type_inclusion [/image/] # whitelist
243
+ validate_mime_type_exclusion [/video/] # blacklist
244
+ end
245
+ end
246
+ ```
247
+
248
+ #### `#size_range`
249
+
250
+ In Shrine file size validations are typically done using the
251
+ `validation_helpers` plugin:
252
+
253
+
254
+ ```rb
255
+ class ImageUploader < Shrine
256
+ plugin :validation_helpers
257
+
258
+ Attacher.validate do
259
+ validate_min_size 0
260
+ validate_max_size 5*1024*1024 # 5 MB
261
+ end
262
+ end
263
+ ```
264
+
265
+ #### `#recreate_versions!`
266
+
267
+ Shrine doesn't provide an automatic mechanism for recreating versions, because
268
+ that is very individual for different situations. For example, sometimes you want to
269
+ regenerate all versions and sometimes just one. However, I wrote a guide
270
+ "[Regenerating versions]" that should help you out with that.
271
+
272
+ ### Models
273
+
274
+ The only thing that Shrine requires from your models is a `<attachment>_data`
275
+ column (e.g. if your attachment is "avatar", you need the `avatar_data` column).
276
+
277
+ #### `.mount_uploader`
278
+
279
+ In Shrine you make include attachment modules directly:
280
+
281
+ ```rb
282
+ Shrine.plugin :sequel
283
+ ```
284
+ ```rb
285
+ class User < Sequel::Model
286
+ include ImageUploader[:avatar]
287
+ end
288
+ ```
289
+
290
+ #### `#<attachment>=`
291
+
292
+ The attachment module adds an attachment setter:
293
+
294
+ ```rb
295
+ user.avatar = File.open("avatar.jpg")
296
+ ```
297
+
298
+ Note that unlike CarrierWave, you cannot pass in file paths, the input needs to
299
+ be an IO-like object.
300
+
301
+ #### `#<attachment>`
302
+
303
+ CarrierWave returns the uploader, but Shrine returns a `Shrine::UploadedFile`,
304
+ a representation of the file uploaded to the storage:
305
+
306
+ ```rb
307
+ user.avatar #=> #<Shrine::UploadedFile>
308
+ user.avatar.methods #=> [:url, :download, :read, :exists?, :delete, ...]
309
+ ```
310
+
311
+ If attachment is missing, nil is returned.
312
+
313
+ #### `#<attachment>_url`
314
+
315
+ This method is simply a shorthand for "if attachment is present, call `#url`
316
+ on it, otherwise return nil":
317
+
318
+ ```rb
319
+ user.avatar_url #=> nil
320
+ user.avatar = File.open("avatar.jpg")
321
+ user.avatar_url #=> "/uploads/ksdf934rt.jpg"
322
+ ```
323
+
324
+ The `versions` plugin extends this method to also accept a version name as the
325
+ argument (`user.avatar_url(:thumb)`).
326
+
327
+ #### `#<attachment>_cache`
328
+
329
+ Shrine doesn't provide this method, instead it expects to recieve the
330
+ attachment through the accessor, you can assign it `<attachment>_data`:
331
+
332
+ ```erb
333
+ <%= form_for @user do |f| %>
334
+ <%= f.hidden_field :avatar, value: @user.avatar_data %>
335
+ <%= f.file_field :avatar %>
336
+ <% end %>
337
+ ```
338
+
339
+ You might also want to look at the `cached_attachment_data` plugin.
340
+
341
+ #### `#remote_<attachment>_url`
342
+
343
+ In Shrine this method is provided by the `remote_url` plugin.
344
+
345
+ #### `#remove_<attachment>`
346
+
347
+ In Shrine this method is provided by the `remove_attachment` plugin.
348
+
349
+ ### Configuration
350
+
351
+ This section walks through various configuration options in CarrierWave, and
352
+ shows what are Shrine's equivalents.
353
+
354
+ #### `root`, `base_path`, `permissions`, `directory_permissions`
355
+
356
+ In Shrine these are configured on the FileSystem storage directly.
357
+
358
+ #### `storage`, `storage_engines`
359
+
360
+ As mentioned before, in Shrine you register storages through `Shrine.storages`,
361
+ and the attachment storages will automatically be `:cache` and `:store`, but
362
+ you can change this with the `default_storage` plugin.
363
+
364
+ #### `fog_*`
365
+
366
+ These options will be set on the soon-to-be-released Fog storage for Shrine.
367
+
368
+ #### `delete_tmp_file_after_storage`, `remove_previously_stored_file_after_update`
369
+
370
+ By default Shrine deletes cached and replaced files, but you can choose to keep
371
+ those files by loading the `keep_files` plugin:
372
+
373
+ ```rb
374
+ Shrine.plugin :keep_files, cached: true, replaced: true
375
+ ```
376
+
377
+ #### `move_to_cache`, `move_to_store`
378
+
379
+ Shrine brings this functionality through the `moving` plugin.
380
+
381
+ ```rb
382
+ Shrine.plugin :moving, storages: [:cache]
383
+ ```
384
+
385
+ #### `validate_integrity`, `ignore_integrity_errors`
386
+
387
+ Shrine does this with validation, which are best done with the
388
+ `validation_helpers` plugin:
389
+
390
+ ```rb
391
+ class ImageUploader < Shrine
392
+ plugin :validation_helpers
393
+
394
+ Attacher.validate do
395
+ # Evaluated inside an instance of Shrine::Attacher.
396
+ if record.guest?
397
+ validate_max_size 2*1024*1024, message: "is too large (max is 2 MB)"
398
+ validate_mime_type_inclusion ["image/jpg", "image/png", "image/gif"]
399
+ end
400
+ end
401
+ end
402
+ ```
403
+
404
+ #### `validate_download`, `ignore_download_errors`
405
+
406
+ Shrine's `remote_url` plugin always rescues download errors and transforms
407
+ them to validation errors.
408
+
409
+ #### `validate_processing`, `ignore_processing_errors`
410
+
411
+ Shrine doesn't offer any built-in ways of rescuing processing errors, because
412
+ it completely depends on how you do your processing. You can easily add your
413
+ own rescuing:
414
+
415
+ ```rb
416
+ class ImageUploader < Shrine
417
+ def process(io, context)
418
+ # processing
419
+ rescue SomeProcessingError
420
+ # handling
421
+ end
422
+ end
423
+ ```
424
+
425
+ #### `enable_processing`
426
+
427
+ You can just do conditionals inside if `Shrine#process`.
428
+
429
+ #### `ensure_multipart_form`
430
+
431
+ No equivalent, it depends on your application whether you need the form to be
432
+ multipart or not.
433
+
434
+ [image_processing]: https://github.com/janko-m/image_processing
435
+ [example app]: https://github.com/janko-m/shrine-example
436
+ [Regenerating versions]: http://shrinerb.com/rdoc/files/doc/regenerating_versions_md.html