Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/shrinerb/shrine

File Attachment toolkit for Ruby applications
https://github.com/shrinerb/shrine

attachment background-jobs direct-upload file-upload filesystem metadata orm rack ruby s3 storage

Last synced: 5 days ago
JSON representation

File Attachment toolkit for Ruby applications

Awesome Lists containing this project

README

        

# [Shrine]

Shrine logo: a red paperclip

Shrine is a toolkit for handling file attachments in Ruby applications. Some highlights:

* **Modular design** – the [plugin system] allows you to load only the functionality you need
* **Memory friendly** – streaming uploads and [downloads][Retrieving Uploads] make it work great with large files
* **Cloud storage** – store files on [disk][FileSystem], [AWS S3][S3], [Google Cloud][GCS], [Cloudinary] and others
* **Persistence integrations** – works with [Sequel], [ActiveRecord], [ROM], [Hanami] and [Mongoid] and others
* **Flexible processing** – generate thumbnails [eagerly] or [on-the-fly] using [ImageMagick] or [libvips]
* **Metadata validation** – [validate files][validation] based on [extracted metadata][metadata]
* **Direct uploads** – upload asynchronously [to your app][simple upload] or [to the cloud][presigned upload] using [Uppy]
* **Resumable uploads** – make large file uploads [resumable][resumable upload] on [S3][uppy-s3_multipart] or [tus][tus-ruby-server]
* **Background jobs** – built-in support for [background processing][backgrounding] that supports [any backgrounding library][Backgrounding Libraries]

If you're curious how it compares to other file attachment libraries, see the
[Advantages of Shrine]. Otherwise, follow along with the **[Getting Started
guide]**.

## Links

| Resource | URL |
| :---------------- | :----------------------------------------------------------------------------- |
| Website & Documentation | [shrinerb.com](https://shrinerb.com) |
| Demo code | [Roda][roda demo] / [Rails][rails demo] |
| Wiki | [github.com/shrinerb/shrine/wiki](https://github.com/shrinerb/shrine/wiki) |
| Discussion forum | [github.com/shrinerb/shrine/discussions](https://github.com/shrinerb/shrine/discussions) |
| Alternate Discussion forum | [discourse.shrinerb.com](https://discourse.shrinerb.com) |

## Setup

Run:

```sh
bundle add shrine
```

Then add `config/initializers/shrine.rb` which sets up the storage and loads
ORM integration:

```rb
require "shrine"
require "shrine/storage/file_system"

Shrine.storages = {
cache: Shrine::Storage::FileSystem.new("public", prefix: "uploads/cache"), # temporary
store: Shrine::Storage::FileSystem.new("public", prefix: "uploads"), # permanent
}

Shrine.plugin :activerecord # loads Active Record integration
Shrine.plugin :cached_attachment_data # enables retaining cached file across form redisplays
Shrine.plugin :restore_cached_data # extracts metadata for assigned cached files
```

Next, add the `_data` column to the table you want to attach files to. For
an "image" attachment on a `photos` table this would be an `image_data` column:

```
$ rails generate migration add_image_data_to_photos image_data:text # or :jsonb
```
If using `jsonb` consider adding a [gin index] for fast key-value pair searchability within `image_data`.

Now create an uploader class (which you can put in `app/uploaders`) and
register the attachment on your model:

```rb
class ImageUploader < Shrine
# plugins and uploading logic
end
```
```rb
class Photo < ActiveRecord::Base
include ImageUploader::Attachment(:image) # adds an `image` virtual attribute
end
```

In our views let's now add form fields for our attachment attribute that will
allow users to upload files:

```erb
<%= form_for @photo do |f| %>
<%= f.hidden_field :image, value: @photo.cached_image_data, id: nil %>
<%= f.file_field :image %>
<%= f.submit %>
<% end %>
```

When the form is submitted, in your controller you can assign the file from
request params to the attachment attribute on the model:

```rb
class PhotosController < ApplicationController
def create
Photo.create(photo_params) # attaches the uploaded file
# ...
end

private

def photo_params
params.require(:photo).permit(:image)
end
end
```

Once a file is uploaded and attached to the record, you can retrieve the file
URL and display it on the page:

```erb
<%= image_tag @photo.image_url %>
```

See the **[Getting Started guide]** for further documentation.

## Inspiration

Shrine was heavily inspired by [Refile] and [Roda]. From Refile it borrows the
idea of "backends" (here named "storages"), attachment interface, and direct
uploads. From Roda it borrows the implementation of an extensible plugin
system.

## Similar libraries

* Paperclip
* CarrierWave
* Dragonfly
* Refile
* Active Storage

## Contributing

Please refer to the [contributing page][Contributing].

## Code of Conduct

Everyone interacting in the Shrine project’s codebases, issue trackers, and
mailing lists is expected to follow the [Shrine code of conduct][CoC].

## License

The gem is available as open source under the terms of the [MIT License].

[Shrine]: https://shrinerb.com
[Advantages of Shrine]: https://shrinerb.com/docs/advantages
[plugin system]: https://shrinerb.com/docs/getting-started#plugin-system
[Retrieving Uploads]: https://shrinerb.com/docs/retrieving-uploads
[FileSystem]: https://shrinerb.com/docs/storage/file-system
[S3]: https://shrinerb.com/docs/storage/s3
[GCS]: https://github.com/renchap/shrine-google_cloud_storage
[Cloudinary]: https://github.com/shrinerb/shrine-cloudinary
[Sequel]: https://shrinerb.com/docs/plugins/sequel
[ActiveRecord]: https://shrinerb.com/docs/plugins/activerecord
[ROM]: https://github.com/shrinerb/shrine-rom
[Hanami]: https://github.com/katafrakt/hanami-shrine
[Mongoid]: https://github.com/shrinerb/shrine-mongoid
[eagerly]: https://shrinerb.com/docs/getting-started#eager-processing
[on-the-fly]: https://shrinerb.com/docs/getting-started#on-the-fly-processing
[ImageMagick]: https://github.com/janko/image_processing/blob/master/doc/minimagick.md#readme
[libvips]: https://github.com/janko/image_processing/blob/master/doc/vips.md#readme
[validation]: https://shrinerb.com/docs/validation
[metadata]: https://shrinerb.com/docs/metadata
[simple upload]: https://shrinerb.com/docs/getting-started#simple-direct-upload
[presigned upload]: https://shrinerb.com/docs/getting-started#presigned-direct-upload
[resumable upload]: https://shrinerb.com/docs/getting-started#resumable-direct-upload
[Uppy]: https://uppy.io/
[uppy-s3_multipart]: https://github.com/janko/uppy-s3_multipart
[tus-ruby-server]: https://github.com/janko/tus-ruby-server
[backgrounding]: https://shrinerb.com/docs/plugins/backgrounding
[Backgrounding Libraries]: https://github.com/shrinerb/shrine/wiki/Backgrounding-Libraries
[Getting Started guide]: https://shrinerb.com/docs/getting-started
[roda demo]: /demo
[rails demo]: https://github.com/erikdahlstrand/shrine-rails-example
[Refile]: https://github.com/refile/refile
[Roda]: https://github.com/jeremyevans/roda
[CoC]: /CODE_OF_CONDUCT.md
[MIT License]: /LICENSE.txt
[Contributing]: https://github.com/shrinerb/shrine/blob/master/CONTRIBUTING.md
[gin index]: https://www.postgresql.org/docs/current/datatype-json.html#JSON-INDEXING