Is it possible to add a validation to accept only .pdf and .doc files using Active Storage?
Currently you have to write your own validator which looks at the attachment's MIME type:
class Item
has_one_attached :document
validate :correct_document_mime_type
private
def correct_document_mime_type
if document.attached? && !document.content_type.in?(%w(application/msword application/pdf))
document.purge # delete the uploaded file
errors.add(:document, 'Must be a PDF or a DOC file')
end
end
end
Also, there are some useful shortcut methods image?
, audio?
, video?
and text?
that check against multiple mime types.
application/vnd.openxmlformats-officedocument.wordprocessingml.document
as stated below. –
Warrant .doc
(the old MS Word format) in which case the MIME type is really application/msword
. The type you mentioned is valid for the newer XML-based .docx
. I guess most people would want to use both in their validators. –
Selfgovernment there is a gem which provides validation for active storage
gem 'activestorage-validator'
https://github.com/aki77/activestorage-validator
validates :avatar, presence: true, blob: { content_type: :image }
validates :photos, presence: true, blob: { content_type: ['image/png', 'image/jpg', 'image/jpeg'], size_range: 1..5.megabytes }
precence
should be presence
–
Nutrient application/pdf
–
Drake Since ActiveStorage doesn't have validations yet, I found the following helps in my forms.
<div class="field">
<%= f.label :deliverable %>
<%= f.file_field :deliverable, direct_upload: true,
accept: 'application/pdf,
application/zip,application/vnd.openxmlformats-officedocument.wordprocessingml.document' %>
</div>
I was looking at https://gist.github.com/lorenadl/a1eb26efdf545b4b2b9448086de3961d
and it looks like on your view you have to do something like this
<div class="field">
<%= f.label :deliverable %>
<%= f.file_field :deliverable, direct_upload: true,
accept: 'application/pdf,
application/zip,application/vnd.openxmlformats-officedocument.wordprocessingml.document' %>
</div>
Now on your model, you can do something like this
class User < ApplicationRecord
has_one_attached :document
validate :check_file_type
private
def check_file_type
if document.attached? && !document.content_type.in?(%w(application/msword application/pdf))
document.purge # delete the uploaded file
errors.add(:document, 'Must be a PDF or a DOC file')
end
end
end
I hope that this helps
class Book < ApplicationRecord
has_one_attached :image
has_many_attached :documents
validate :image_validation
validate :documents_validation
def documents_validation
error_message = ''
documents_valid = true
if documents.attached?
documents.each do |document|
if !document.blob.content_type.in?(%w(application/xls application/odt application/ods pdf application/tar application/tar.gz application/docx application/doc application/rtf application/txt application/rar application/zip application/pdf image/jpeg image/jpg image/png))
documents_valid = false
error_message = 'The document wrong format'
elsif document.blob.byte_size > (100 * 1024 * 1024) && document.blob.content_type.in?(%w(application/xls application/odt application/ods pdf application/tar application/tar.gz application/docx application/doc application/rtf application/txt application/rar application/zip application/pdf image/jpeg image/jpg image/png))
documents_valid = false
error_message = 'The document oversize limited (100MB)'
end
end
end
unless documents_valid
errors.add(:documents, error_message)
self.documents.purge
DestroyInvalidationRecordsJob.perform_later('documents', 'Book', self.id)
end
end
def image_validation
if image.attached?
if !image.blob.content_type.in?(%w(image/jpeg image/jpg image/png))
image.purge_later
errors.add(:image, 'The image wrong format')
elsif image.blob.content_type.in?(%w(image/jpeg image/jpg image/png)) && image.blob.byte_size > (5 * 1024 * 1024) # Limit size 5MB
image.purge_later
errors.add(:image, 'The image oversize limited (5MB)')
end
elsif image.attached? == false
image.purge_later
errors.add(:image, 'The image required.')
end
end
end
And in job Destroy
class DestroyInvalidationRecordsJob < ApplicationJob
queue_as :default
def perform(record_name, record_type, record_id)
attachments = ActiveStorage::Attachment.where(name: record_name, record_type: record_type, record_id: record_id)
attachments.each do |attachment|
blob = ActiveStorage::Blob.find(attachment.blob_id)
attachment.destroy
blob.destroy if blob.present?
end
end
end
I was doing direct uploads with ActiveStorage. Since validators don't exist yet I simply overwrote the DirectUploadsController Create
method:
# This is a kind of monkey patch which overrides the default create so I can do some validation.
# Active Storage validation wont be released until Rails 6.
class DirectUploadsController < ActiveStorage::DirectUploadsController
def create
puts "Do validation here"
super
end
end
also need to overwrite the route:
post '/rails/active_storage/direct_uploads', to: 'direct_uploads#create'
+1 for using gem 'activestorage-validator'
with ActiveStorage
In your model you can validate doc
, docx
and pdf
formats this way:
has_one_attached :cv
validates :cv, blob: { content_type: ['application/msword', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'application/pdf'], size_range: 0..5.megabytes }
Adding a gem for just a few lines of code is not always needed. Here's a working example based on a small alteration on the example above.
validate :logo_content_type, if: -> { logo.attached? }
def logo_content_type
allowed = %w[image/jpeg image/jpeg image/webp image/png]
if allowed.exclude?(logo.content_type)
errors.add(:logo, message: 'Logo must be a JPG, JPEG, WEBP or PNG')
end
end
© 2022 - 2024 — McMap. All rights reserved.