Direct Image Upload in Rails 7 Using Active Storage and Cloudinary

Active Storage is a Rails module used as a gateway to upload files to cloud services. Cloudinary is one such service and a complex platform that allows developers to store, transform, optimize, and deliver images and videos. Cloudinary has a free plan available, and it's pretty easy to start with them. In this article, we will cover uploading images in Rails 7 using Active Storage and Cloudinary. We will be using Rails 7.1.2 and Ruby 3.3.0.

To exemplify, we will build a simple blog app, with blog posts, and each post will have an intro image attached. We will install and configure Cloudinary and Active Storage, then discuss how we can directly upload files to Cloudinary from our application, and finally how we can deliver images in our application.

Create a New Application

Let's start by creating a new application. In the terminal, we type:

rails new blog_app

After the creation of our new application, we move into the newly generated app directory:

cd blog_app 

Install the ImageProcessing and Cloudinary Gems

To enable image processing and Cloudinary integration in our Rails application, we'll install the required gems. We will install the ImageProcessing gem, which facilitates the creation of derivative images from the originals. It utilizes either ImageMagick or libvips libraries for image processing. Before installing the gem, ensure that at least one of these libraries is installed on your system. Visit their respective websites for installation instructions based on your operating system.  Also, we’ll install the Cloudinary gem.

In your Gemfile, uncomment the following line to include the ImageProcessing gem:

gem "image_processing", "~> 1.2"

Then add the Cloudinary gem:

gem "cloudinary", "~> 1.28"

Then run:

bin/bundle install

This command will download and install the specified gems, preparing our Rails application for image processing and Cloudinary integration.

Install the Active Storage Module

To install the Active Storage module, we'll use the provided generator:

bin/rails active_storage:install

Running this command, will not only set up the necessary configurations but also generate a migration file responsible for creating essential tables: active_storage_blobs, active_storage_attachments, and active_storage_variant_records. Proceed to execute the migration by running:

bin/rails db:migrate

Configure Cloudinary and Integrate it with Active Storage

To integrate Cloudinary into your Rails application, follow these steps to configure your credentials and seamlessly integrate them with Active Storage.

1. Create Cloudinary Configuration

Create a file named cloudinary.rb within the app/initializers/ directory to store your Cloudinary credentials obtained from your Cloudinary dashboard:

Cloudinary.config do |config|
  config.cloud_name = "YOUR_CLOUD_NAME"
  config.api_key = "YOUR_API_KEY"
  config.api_secret = "YOUR_API_SECRET"
end

Replace "YOUR_CLOUD_NAME", "YOUR_API_KEY", and "YOUR_API_SECRET" with your actual Cloudinary credentials.

2. Update Active Storage Configuration

Edit the storage.yml file located in the app/config/ directory to include Cloudinary as a service:

cloudinary:
  service: Cloudinary

3. Integrate Cloudinary with Active Storage

To utilize Cloudinary as the storage service for Active Storage in your production and development environments, update the respective environment files (production.rb and development.rb) located in the config/environments/ directory.

Replace the line:

config.active_storage.service = :local

with:

config.active_storage.service = :cloudinary

These configurations ensure that Active Storage utilizes Cloudinary as the storage service for file uploads in your Rails application.

Create and Edit the Post Resource

1. Scaffold the Post Resource

Let's generate a scaffold for the Post resource:

bin/rails g scaffold Post title:string content:text

Let's execute the migration to create the necessary database tables:

bin/rails db:migrate

Let's set the root route of our application to the posts index action. In the config/routes.rb file add this at the top:

root "posts#index"

2. Enable Image Uploads for Posts

In the app/models/post.rb file, modify the Post model to allow for image attachments using Active Storage:

has_one_attached :intro_image

This will create a one-to-one mapping between the post records and files. 

3. Update Controller Parameters

Within the posts controller (app/controllers/posts_controller.rb), let's ensure that the intro_image parameter is permitted in the post parameters:

def post_params
  params.require(:post).permit(:title, :content, :intro_image)
end

Direct Upload Images to Cloudinary

We can directly upload images to the cloud by using the Active Storage JavaScript library. Let's do it.

1. Include Active Storage in the Application

Edit the config/importmap.rb file to include the Active Storage JavaScript library:

pin "@rails/activestorage", to: "activestorage.esm.js"

In app/javascript/application.js, import and initialize the Active Storage library:

import * as ActiveStorage from "@rails/activestorage"
ActiveStorage.start()

2. Implement Direct Image Upload

Now, we can use the file_field helper, with the direct_upload option set to true. In the form partial within the app/views/posts/ directory, let's add such a field:

<div>
  <%= form.label :_intro_image, style: "display: block" %>
  <%= form.file_field :intro_image, direct_upload: true %>
</div>

In the show view(app/views/posts/show.html.erb), use the cl_image_tag helper to render the uploaded image with specified transformations:

<%= cl_image_tag(@post.intro_image.key, width: 400, height: 400, crop: "crop", gravity: "center", alt: "post intro image") %>

This code snippet showcases the cl_image_tag helper, applying transformations like cropping and specifying width, height, and gravity for the displayed image.

Conclusion

In this tutorial, we've seamlessly integrated Cloudinary with Active Storage in our Rails 7 application, enabling direct image uploads to Cloudinary's robust platform. Leveraging the power of Active Storage's JavaScript library, we enabled users to upload images directly to the cloud, simplifying the image upload process.

Post last updated on April 29, 2024