Rails Image Uploading 101

Rebecca Hickson
Level Up Coding
Published in
6 min readJan 23, 2021

--

Photo by DESIGNECOLOGIST on Unsplash

Imagine the internet without any graphics. You can’t go on Facebook to see your 2nd cousin’s best friend’s new baby, you can’t scroll through Instagram for the 46th time today, and memes? never heard of them! Images are integral to our enjoyment of websites and applications, so if you are a fledgling Rails developer it is no surprise that you would want to include them in your project. However if you ask your favorite search engine for advice, you can easily be overwhelmed with options. This article is here to guide you through a basic implementation of photos into your project.

Here’s the technology we’ll be using:

Let’s Get Started

Photo by Gia Oris on Unsplash

Set up Active Storage

Begin by running:

rails active_storage:install

Active Storage will create a migration for you that will set up all of the necessary tables for you. If you navigate to the migration it should look something like this:

Screenshot of CreateActiveStorageTables migration

Now, that looks like a lot and likely has some things that you don’t 100% understand, but don’t let that intimidate you! Feel free to research the ins and outs of this at your leisure, but for now, you can trust that Active Storage knows what it’s doing. Go ahead and run:

rails db:migrate

Add Association

The next step is to make sure that your model is ready to accept the photo. Add this line of code to whichever model will have an image attached to it.

has_one_attached :image

You can call the image whatever you please :avatar, :main_image, :profile_pic Whatever is most accurate for your project is fine; this is how you will refer to the attached image elsewhere. You also have the option to use has_many_attached, but we’ll be focusing on attaching one image today.

Local Storage

Take a peek at your config/storage.yml file. You have the option to set up hosting services with a provider like Amazon S3, Google Cloud Storage, or Microsoft Azure Storage. By default, Active Storage will set you up to host the images locally, which is totally fine so long as your application is in development. If you see this, you’re good to go!

Screenshot of locally hosted storage.yml file

Strong Params

If you are using Strong Params (which you probably should be!), you must allow the image to be passed in. To do so, just add whatever you chose to call the image into your list of permitted params

Screenshot of Strong Params, marking the :image key at the end

Adding Images

Photo by Jakob Owens on Unsplash

Upload a Photo

Now that you’re all set up, let’s create a form to allow your user to upload a photo.

Screenshot of a form, marking the :image fields

If you have already created your form, this is all that you need to add:

<p><%= f.label :image%><%= f.file_field :image, accept: 'image/png, image/gif, image/jpeg' %></p>

Make sure that you use whatever you selected previously in place of :image, but leave image/png, etc. the same as above.

This code creates the file upload structure that you may be familiar with on most websites, and it limits the user to select only .png, .gif, and .jpg image elements to help prevent bad data from entering your database.

Seed Your Database

It’s possible to seed your database with models that already have images attached. If you choose to, make sure that you add the images into your project so that other developers will have access to them. I chose to have mine in a seed_images folder to make it crystal clear to anyone looking at the database where things were.

Screenshot of app directory, showing the nested folders for images

Once you have your seed images ready to go, jump over to your db/seeds.rb. Start by creating a new instance like you normally would. At the end, you’ll tag on this code:

.image.attach(io: File.open('app/assets/images/seed_images/bridal/bridal_1.jpg'), filename: 'bridal_1.jpg')
Screenshot of sample seed file code

The argument for File.open will be the relative path to wherever you saved your images, and .image will again match your selection from earlier. To seed your database, run:

rails db:seed

NOTE: Once you start adding images to your seeds, it will slow down the seeding process, and your database may timeout if you add too many. Consider creating multiple seed files or you can extend the timeout period in your config/database.yml file.

Validations

Photo by Soragrit Wongsa on Unsplash

When you’re working with a database, it’s important to make sure everything is where and how you expect it to be and to prevent unwanted elements from sneak through. Validations can be used to ensure this, but wait! There are no built-in validations for image attachments. Luckily, we’ve got a gem for that!

Enter, the Active Storage Validations!

If you haven’t already, go ahead and add this gem in your Gemfile:

gem 'active_storage_validations'

There are many things that this gem can help you with, but let’s start with the basics. If you want to validate that an image is attached, add this code to your Model:

validates :image, attached: true

Nice and easy!

Displaying Images

Photo by Leonardo Yip on Unsplash

Basic Display

Now that we have uploaded some images to our database, we want to use them in our application! You may add this code in the view where you would like to display the image. Make sure that you have set the variable @photo to the instance you would like to display and the .image should match your selection from above

<img src="<%= (url_for(@photo.image)) %>">

This is our basic image tag, with an ERB tag finding our photo’s image URL and feeding it into the src.

Styling

You can add CSS classes into this tag, just like you normally would. Since you don’t know what size photo a user may upload, you should be careful about just displaying it at full size. A basic CSS styling that can be helpful is:

.full-img {object-fit: contain;height: 100%;width: 500px;padding-top: 20px;padding-bottom: 20px;}

If you add this class to your img tag, it will maintain the photos aspect ratio while sizing it down to a width of 500px (read more about how object-fit works here) and adds padding to the top and bottom to prevent it from pressing up against other content on your page.

What styling you choose is up to you! Make sure to account for abnormally large pictures, and your application should be looking great in no time.

Conclusion

Photo by Mick Haupt on Unsplash

Images are a key part of why most users go online, and they can add a lot to your application. There is a wealth of information out there about hosting images, and it can sometimes feel overwhelming. I hope that this article was helpful in breaking it down for you, and that your application is working just how you hoped! Remember, this guide set you up for hosting images locally, which is wonderful for development and learning, but you will want to use a provider once your site goes into production.

I dove into Active Support while building my Rails application, Take Your Pix. If you would like to see this code in action, the development version is available on my GitHub. Please feel free to reach out to me if you have any questions!

--

--