Rails Active Storage Cheatsheet
Without an introduction, here is the table of content:
- Rails Active Storage Cheatsheet
Install Active Storage
Only for Rails version 5.2 and up (Rails 5.2.X & Rails 6.X.X).
- Install
rails active_storage:install
- 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 :
- Add
gem 'image_processing', '~> 1.2'
to your Gemfile. - Install MiniMagick for image variants.
- To generate previews of PDFs, install Poppler.
- 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)
I posted this originally in Github as a Gist: here
Top comments (0)