Active Storage doesn't have validations yet.
We can restrict the accepted file types in the form:
<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>
And add a custom validation in the model:
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))
errors.add(:document, 'Must be a PDF or a DOC file')
end
end
end
This is useful, but has one caveat that one might or might not care about, so I'm writing it out here in case it helps anyone.
The validation proposed in this gist will check the file after it is uploaded. This might be a problem especially when using a paid cloud service.
The following is another method, that doesn't send the file over to the cloud service at all. I don't really like it, and it probably breaks the MVC, but I'm not sure there is another way if we don't want the file to be sent.
So what I've done in my case, is validate in the controller. Yes, it's weird. But even calling object.file = will upload our file to ie S3 even if we don't call object.save!
We can make it a bit nicer by having a constant in the model like this:
The controller can use this contant then and check with the param[:file].content_type and param[:file].size to check if the file can be accepted. The controller can then add errors on the object without assigning anything to the file field.