ActiveStorage File Attachment Validation

前端 未结 7 541
暖寄归人
暖寄归人 2021-01-31 10:01

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

7条回答
  •  温柔的废话
    2021-01-31 10:33

    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.

提交回复
热议问题