Is there a way to validate attachments with ActiveStorage? For example, if I want to validate the content type or the file size?
Something like Paperclip\'s approach wou
Here is my solution to validate content types in Rails 5.2, that as you may know it has the pitfall that attachments are saved as soon as they are assigned to a model. It may also work for Rails 6. What I did is monkey-patch ActiveStorage::Attachment
to include validations:
config/initializers/active_storage_attachment_validations.rb
:
Rails.configuration.to_prepare do
ActiveStorage::Attachment.class_eval do
ALLOWED_CONTENT_TYPES = %w[image/png image/jpg image/jpeg].freeze
validates :content_type, content_type: { in: ALLOWED_CONTENT_TYPES, message: 'of attached files is not valid' }
end
end
app/validators/content_type_validator.rb
:
class ContentTypeValidator < ActiveModel::EachValidator
def validate_each(record, attribute, _value)
return true if types.empty?
return true if content_type_valid?(record)
errors_options = { authorized_types: types.join(', ') }
errors_options[:message] = options[:message] if options[:message].present?
errors_options[:content_type] = record.blob&.content_type
record.errors.add(attribute, :content_type_invalid, errors_options)
end
private
def content_type_valid?(record)
record.blob&.content_type.in?(types)
end
def types
Array.wrap(options[:with]) + Array.wrap(options[:in])
end
end
Due to the implementation of the attach
method in Rails 5:
def attach(*attachables)
attachables.flatten.collect do |attachable|
if record.new_record?
attachments.build(record: record, blob: create_blob_from(attachable))
else
attachments.create!(record: record, blob: create_blob_from(attachable))
end
end
end
The create!
method raises an ActiveRecord::RecordInvalid
exception when validations fail, but it just needs to be rescued and that's all.