Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save jotolo/e354744de94f21bcba1a27c6e88eb77f to your computer and use it in GitHub Desktop.
Save jotolo/e354744de94f21bcba1a27c6e88eb77f to your computer and use it in GitHub Desktop.
A Ruby on Rails Active Storage Cheatsheet

Rails Active Storage Cheatsheet


Install Active Storage

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

  1. Install
rails active_storage:install
  1. Run migration
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
class User < ApplicationRecord

  has_one_attached :document
end
  • Many attachments
class User < ApplicationRecord

  has_many_attached :documents
end

Controller

  • One attachment
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
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
<%= form.file_field :document %>
  • Many attachments
<%= 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 for image variants.
  3. To generate previews of PDFs, install Poppler.
  4. To generate previews of Videos, install FFmpeg.

Display an image (when document is an image)

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

if user.documents.attached?
  • One attachment
<% if user.document.attached? %>
  <%= image_tag user.document %>
<% end %>
  • Many attachments

At least one document is attached

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

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

Generate a preview with preview

For PDFs or videos.

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

<% 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:

user.document.content_type

Video attachment file size:

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.

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

Validation with activestorage-validator gem

To install activestorage-validator gem add in your application's Gemfile:

gem 'activestorage-validator'

To use this gem, in your model add:

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 in Rails repository in Github.

# 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)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment