A Ruby On Rails Active Storage Cheatsheet
Published: 2020-05-26 22:48:48

# Rails Active Storage Cheatsheet

Without an introduction, here is the table of content:

- [Rails Active Storage Cheatsheet](#rails-active-storage-cheatsheet)
  - [Install Active Storage](#install-active-storage)
  - [Usage](#usage)
    - [Model](#model)
    - [Controller](#controller)
    - [Views (in ERB)](#views-in-erb)
    - [Display Image and its variants or Preview (PDF or Video)](#display-image-and-its-variants-or-preview-pdf-or-video)
      - [Install this libraries first](#install-this-libraries-first)
      - [Display an image (when document is an image)](#display-an-image-when-document-is-an-image)
      - [Generate a variant of an image with `variant`](#generate-a-variant-of-an-image-with-variant)
      - [Generate a preview with `preview`](#generate-a-preview-with-preview)
      - [Don't know the type of document? Use `representation`](#dont-know-the-type-of-document-use-representation)
    - [Content type and size](#content-type-and-size)
    - [Attach a local file](#attach-a-local-file)
    - [Validation with activestorage-validator gem](#validation-with-activestorage-validator-gem)
    - [Select all records with an attachment](#select-all-records-with-an-attachment)

---

## Install Active Storage

Only for Rails version 5.2 and up (Rails 5.2.X & Rails 6.X.X).

1. Install

```sh
rails active_storage:install
```

1. Run migration

```sh
rails db:migrate
```

## Usage

We will use User model with attachment(s) name document(s), this document can be an image or PDF or video or any other type.

### Model

- **One attachment**

```ruby
class User < ApplicationRecord

  has_one_attached :document
end
```

- **Many attachments**

```ruby
class User < ApplicationRecord

  has_many_attached :documents
end
```

### Controller

- **One attachment**

```ruby
class UsersController < ApplicationController
  # your controller methods (index, show ...).
  private

  # Only allow a list of trusted parameters through.
  def user_params
    params.require(:yser).permit(:first_name, :last_name, :document)
  end
end
```

- **Many attachments**

```ruby
class UsersController < ApplicationController
  # your controller methods (index, show ...).
  private

  # Only allow a list of trusted parameters through.
  def user_params
    params.require(:user).permit(:first_name, :last_name, documents: [])
  end
end
```

### Views (in ERB)

Form filed:

- **One attachment**

```erb
<%= form.file_field :document %>
```

- **Many attachments**

```erb
<%= form.file_field :documents, multiple: true %>
```

### Display Image and its variants or Preview (PDF or Video)

#### Install this libraries first

First to generate **variants** and **previews** of PDFs and videos, you will need to :

1. Add `gem 'image_processing', '~> 1.2'` to your Gemfile.
2. Install [MiniMagick](https://imagemagick.org/script/download.php) for image variants.
3. To generate previews of PDFs, install [Poppler](https://poppler.freedesktop.org).
4. To generate previews of Videos, install [FFmpeg](https://www.ffmpeg.org/download.html).

#### Display an image (when document is an image)

To check if there is an image attached before displaying it use:

```ruby
if user.documents.attached?
```

- **One attachment**

```erb
<% if user.document.attached? %>
  <%= image_tag user.document %>
<% end %>
```

- **Many attachments**

At least one document is attached

```erb
<% if user.documents.attached? %>
  <% user.documents.each do |document| %>
    <%= image_tag document %>
  <% end %>
<% end %>
```

#### Generate a variant of an image with `variant`

Don't forget `user.document` should be an **image** in this case.

```erb
<%= image_tag user.document.variant(resize_to_limit: [75, 75]).processed %>
```

> `.processed` method will store the variant for performance reasons.

For more variant transformations check [image_processing docs](https://github.com/janko/image_processing#installation).

#### Generate a preview with `preview`

For PDFs or videos.

```erb
<% if user.document.previewable? %>
  <%= image_tag(user.document.preview(resize: '200x200') %>
<% end %>
```

> `.previewable?` method will check if you can create a preview of the document attached.

#### Don't know the type of document? Use `representation`

```erb
<% if user.document.representable? %>
  <%= image_tag(user.document.representation(resize: '200x200') %>
<% end %>
```

> `.representable?` method will check if you can create a preview or a variant of the document attached.

### Content type and size

Document attachment content type:

```ruby
user.document.content_type
```

Video attachment file size:

```ruby
user.video.byte_size
```

### Attach a local file

In tests for example we want to be able to save/attach local files in Active Storage.

```ruby
user.picture.attach(io: File.open('/path/to/file'), filename: 'my_picture.png')
```

### Validation with activestorage-validator gem

To install [activestorage-validator](https://github.com/aki77/activestorage-validator) gem add in your application's Gemfile:

```ruby
gem 'activestorage-validator'
```

To use this gem, in your model add:

```ruby
class User < ApplicationRecord
  has_one_attached :avatar
  has_many_attached :photos

  validates :avatar, presence: true, blob: { content_type: :image } # supported options: :image, :audio, :video, :text
  validates :photos, presence: true, blob: { content_type: ['image/png', 'image/jpg', 'image/jpeg'], size_range: 1..5.megabytes }
  # validates :photos, presence: true, blob: { content_type: %r{^image/}, size_range: 1..5.megabytes }
end
```

### Select all records with an attachment

From the comment in this [issue](https://github.com/rails/rails/issues/32295#issuecomment-374304126) in Rails repository in Github.

```ruby
# Assuming a model defined like so:
class Post < ApplicationRecord
  has_one_attached :image
end

# ...you can join against :image_attachment to select posts having attached images:
Post.joins(:image_attachment).where('published_at >= ?', Time.now)
```

> I posted this originally in Github as a Gist: [here](https://gist.github.com/naoufalelh/d49944fb8f9bdac94bdba5d1aae15b10)