Active Storage has the kind of easy-to-use features you’d expect from a Rails core library. Image variants, direct uploads, even JavaScript hooks are among my favorites.

But so far Rails has not added the ability to add validations to file attachments. Requiring that an attachment be present or have a particular content-type is essential. It looks like they are working on it for Rails 6, but what do we do in the meantime..?

Luckily it’s pretty easy to add custom validators to add in the missing functionality!

I’ve already shown how to add the attachment presence validator to your Rails apps. Now I’ll show how to add a validator that restricts an attachment’s content-type. You can use this, for example, to ensure that your users only upload PNG, JPEG, or GIF files for their profile images. Or that documents are only PDF or DOC format.

I’ll also include a handy RSpec matcher that I use in my unit tests to test the validation.

Restricting the content-type of an attachment

The validation accepts an array of content-type strings which serves as an allow list. Add this to your model and attachments will only be valid if its file type is in the list.

class Person < ApplicationModel   
  has_one_attached :avatar

  validates :avatar, content_type: ["image/png", "image/jpeg"]

You’ll find the code for the validator here

Test allowed/denied content-types using this RSpec matcher

I use shoulda-matchers in my unit tests for a quick sanity check on my validations. Below is an RSpec matcher modeled after the allow_format matcher that tests validate_format_of. You can pass it a set of allowable content-types that should be valid. You can also pass it a set of disallowed content-types that shouldn’t be valid.

describe Person do
  it { allow_content_types("image/png", "image/jpeg").for(:avatar) }
  it { is_expected.not_to allow_content_type("image/gif").for(:avatar) }

You’ll find the code for the matcher here

What other validators are missing from Active Storage?

So far the main validations I’ve missed from Active Storage are for presence and content-type. Which ones do you wish you had for your own work?

Share your thoughts in the comments below!

One of my favorite features of Active Storage is the variant method. Not only is it super easy to use, but it’s also very powerful. You can create image transformations using any option that’s supported by ImageMagick.

Unfortunately, I’ve found the documentation for these options isn’t that accessible…

In my next post I’ll be discussing how options are passed to the variant method. I’ll share the best online resources and documentation to take the mystery out of what transformations are possible and how to achieve them. You’ll also learn how to fix upside down images, how to deal with images with different aspect ratios, and more.

Read it here: What Options Can Be Passed to the Active Storage variant Method?