Ruby on Rails

Real-time image resizing, automatic optimization, and file uploading in Ruby on Rails using ImageKit.io.

This is a quick start guide to show you how to integrate ImageKit in the Ruby on Rails application. The code samples covered here are hosted on Github - https://github.com/imagekit-samples/quickstart/tree/master/ruby-on-rails.

This guide walks you through the following topics:

Setting up ImageKit Ruby SDK

For this tutorial, we will create a fresh rails application and work with it. If you already have an existing Rails app, it is also possible to use that, although you would need to modify the terminal commands and configurations in this tutorial as applicable.

Let's create a new rails application. Create a new directory and enter the command:

rails new sample-app

Now, navigate to the newly created directory, and run the app:

rails server

In your web browser, navigate to http://localhost:3000/

You should see a generic welcome message (Yay! You're on Rails!).

Welcome message for a fresh Ruby on Rails application

Next, to use ImageKit functionality in our app, we will create a new controller with the following command:

rails generate controller Welcome

This will generate a few scaffolding files for you. Go to config/routes.rb and add the following lines:

get 'welcome/index'
root 'welcome#index'

Here, we are doing two things:

  1. One, creating a route at the path welcome/index, to direct requests coming on that path to go to the index action of the Welcome controller, which we will add soon.

  2. Second, we are declaring the root path to be directed to welcome/index. This means that all requests on http://localhost:3000/ will go to http://localhost:3000/welcome/index

Installing the SDK

First, add this line to your Gemfile to add the 'imagekitio' gem as a dependency.

gem 'imagekitio'

Next, run the bundle install command to install the imagekitio gem from the RubyGems repository.

bundle install

Initializing the SDK

Before the SDK can be used, let's learn about and configure the requisite authentication parameters that need to be provided to the SDK.

Open the app/controllers/application_controller.rb file and add your public and private API keys, as well as the URL Endpoint as follows: (You can find these keys in the Developer section of your ImageKit Dashboard)

class ApplicationController < ActionController::Base
before_action :init_ik
def init_ik
private_key = "YOUR_PRIVATE_KEY"
public_key = "YOUR_PUBLIC_KEY"
# default value for endpoint is: https://ik.imagekit.io/<YOUR_IMAGEKIT_ID>/
url_endpoint = "YOUR_URL_ENDPOINT"
# here we initialize an instance of the SDK, which we will use to work with images
@imagekitio = ImageKit::ImageKitClient.new(private_key, public_key, url_endpoint)
end
end

Restart the application

rails server

The home screen will display an error message stating that the index action could not be found for the WelcomeController. Let's fix that.

Rendering images in Ruby on Rails

Open up the project in your text editor of choice, and navigate to app/controllers/welcome_controller.rb. Edit it to make it look like the following:

class WelcomeController < ApplicationController
def index
# Configure your URL here
end
end

Here, declare a variable to store the image URL generated by the SDK. Like this:

class WelcomeController < ApplicationController
def index
@image_url = @imagekitio.url({
path: 'default-image.jpg',
})
end
end

Now, @image_url has the URL https://ik.imagekit.io/<your_imagekit_id>/default-image.jpg stored in it. This variable can now be read by the index view, where we will display the image.

Go to app/views/welcome/index.html.erb, and add the following line:

<%= image_tag @image_url %>

This fetches the image from the URL stored in @image_url that we created in the controller file.

Rerunning the server should now display this default image in its full size:

Image in its original dimensions (1000px * 1000px)

Common image manipulation in Ruby on Rails

Let’s now learn how to manipulate images using ImgeKit transformations.

Height and width manipulation

To resize an image along with its height or width, we need to pass the transformation as an array to the imagekitio.url() method.

Let’s resize the default image to 200px height and width:

class WelcomeController < ApplicationController
def index
@image_url = @imagekitio.url({
path: 'default-image.jpg',
transformation: [{
height: "200",
width: "200",
}]
})
end
end

Transformation URL:

https://ik.imagekit.io/violetviolinist/tr:h-200,w-200/default-image.jpg?ik-sdk-version=ruby-1.0.6

Refresh your browser to get the resized image.

Resized image (200px * 200px)

Chained transformation

Chained transformations provide a simple way to control the sequence in which transformations are applied.

Let’s try it out by resizing an image, then rotating it:

class WelcomeController < ApplicationController
def index
@image_url = @imagekitio.url({
path: 'default-image.jpg',
transformation: [{
height: "300",
width: "200",
}]
})
end
end

Transformation URL:

https://ik.imagekit.io/violetviolinist/tr:h-300,w-200/default-image.jpg?ik-sdk-version=ruby-1.0.5

Output Image:

Resized and cropped (200px * 300px)

Now, rotate the image by 90 degrees.

class WelcomeController < ApplicationController
def index
@image_url = @imagekitio.url({
path: 'default-image.jpg',
transformation: [
{
height: "300",
width: "200",
},
{
rt: 90,
},
],
})
end
end

Chained Transformation URL:

https://ik.imagekit.io/violetviolinist/tr:h-300,w-200:rt-90/default-image.jpg?ik-sdk-version=ruby-1.0.5

Output Image:

Resized, then rotated

Let’s flip the order of transformation and see what happens.

class WelcomeController < ApplicationController
def index
@image_url = @imagekitio.url({
path: 'default-image.jpg',
transformation: [
{
rt: 90,
},
{
height: "300",
width: "200",
},
],
})
end
end

Chained Transformation URL:

https://ik.imagekit.io/violetviolinist/tr:rt-90:h-300,w-200/default-image.jpg?ik-sdk-version=ruby-1.0.5

Output Image:

Rotated, then resized

Adding overlays to images in Ruby on Rails

ImageKit.io allows you to add text and image overlay dynamically.

Text overlay

Text overlay can be used to superimpose text on an image. For example:

class WelcomeController < ApplicationController
def index
@image_url = @imagekitio.url({
path: 'default-image.jpg',
transformation: [{
height: "300",
width: "300",
overlay_text: 'ImageKit',
overlay_text_font_size: 50,
overlay_text_color: '0651D5',
}],
})
end
end

Transformation URL:

https://ik.imagekit.io/violetviolinist/tr:h-300,w-300,ot-ImageKit,ots-50,otc-0651D5/default-image.jpg?ik-sdk-version=ruby-1.0.5

Output Image:

Text Overlay (300px * 300px)

Image overlay

Image overlay can be used to superimpose an image on another image. For example, we will upload a while logo image on this link into our account and use it for the overlay image.

Base Image: default-image.jpg

Overlay Image: overlay-image.png

class WelcomeController < ApplicationController
def index
@image_url = @imagekitio.url({
path: 'default-image.jpg',
transformation: [{
height: "300",
width: "300",
overlay_image: "overlay-image.png"
}],
})
end
end

Transformation URL:

https://ik.imagekit.io/violetviolinist/tr:h-300,w-300,oi-overlay-image.png/default-image.jpg?ik-sdk-version=ruby-1.0.6

Output Image:

Overlay image over another image

Secure signed URL generation

You can use the SDK to generate a signed URL of an image, that expires in a given number of seconds.

# app/controllers/welcome_controller.rb
def signed_url
@signed_image_url = @imagekitio.url({
path: 'default-image.jpg',
signed: true,
expire_seconds: 10,
})
end
# config/routes.rb
get 'welcome/signed_url'
# app/controllers/views/welcome/signed_url.html.erb
<span>
<%= @signed_image_url %>
</span>

The above snippets create a signed URL with an expiry time of 10 seconds.

Signed URL generation

Uploading file in Ruby on Rails application

There are two different methods of uploading a file to your ImageKit Media Library:

  1. Direct image upload.

  2. Attaching the image to a model using CarrierWave.

Direct image upload

First, add the following code to app/views/welcome/index.html.erb:

<h3>File Upload</h3>
<%= form_with(url: {action: :upload}, multipart: true) do %>
<%= file_field_tag 'picture' %>
<%= submit_tag "Upload" %>
<% end %>
<br>
<% flash.each do |name, msg| %>
<%= content_tag :div, msg, class: "alert alert-info" %>
<% end %>

This creates a simple form with a file upload field and a submit button. The form submits the file to the path /welcome/upload. We need to add this path to our routes. Go to config/routes.rb, and add the following line:

post 'welcome/upload'

Now, we have the route and the HTML markup set up to submit a file for uploading. Let's introduce the controller action 'welcome#upload' to receive the file and upload it to the Media Library. Go to app/controllers/welcome_controller.rb, and add the following method:

def upload
uploaded_file = params[:picture]
output = @imagekitio.upload_file
(
file = uploaded_file, # required
file_name= "new_file.jpg", # required
options= {response_fields: 'tags', tags: ["hello"]}
)
if output[:error]
redirect_to "/", notice: "There was some problem uploading your image"
else
redirect_to "/", notice: "Your image has been uploaded successfully with the name of #{output[:response]["name"]}" end
end

Here, we first extract the file from the :picture property of the params object, and then upload the file to our Media Library by the name of new_file.jpg, using the upload_file() API. We also attach an example tag 'hello' to the image.

Now, refresh the home page, and you should see the upload field.

Upload field

Select an image/file from your local computer, and click on the Upload button. A success message shall flash below the file field.

Your image has been uploaded successfully with the name <NAME_OF_FILE>

Now, after upload, if you go to the Media Library section of your ImageKit dashboard, you should see the newly uploaded image.

If you get an authentication error during upload, verify that the API keys are configured correctly.

Fetching uploaded file

Fetch the uploaded image and display it in the UI by adding this line to your app/views/welcome/index.html.erb.

<%= image_tag "https://ik.imagekit.io/<YOUR_IMAGEKIT_ID>/<FILE_NAME>" %>

The app should render your uploaded image correctly.

Attaching the image to a model (using CarrierWave)

You can attach an image as an attribute of one of your models, making it convenient to write a model-oriented code. This method uses the CarrierWave gem, which is a dependency of the imagekitio gem. First, add the following configurations to config/environments/development.rb and config/environments/production.rb

config.imagekit =
{
private_key: "<your-private-key>",
public_key: "<your-public-key>",
url_endpoint: "<endpoint-url>"
}

Next, we'll create an entity called an uploader.

rails g uploader <Uploading_attribute_name>
# For example if you want to create uploader for Picture attribute then use
rails g uploader Picture
# Generated uploader's path will be app/uploaders/picture_uploader.rb

Now, go to the generated uploader file - app/uploaders/<name>_uploader.eb, and enter the following code. The options configuration is optional.

# Set store as imagekit_store
storage :imagekit_store
# If you want to add uploading options then create this method inside uploader file as an example
def options
options =
{
response_fields: 'isPrivateFile, tags',
tags: ["Rails SDK uploads"],
use_unique_file_name: false,
folder: "your_directory/"
}
end
# If you want to set upload dir then you can use following method or you can also use options method.
# This method shuld return string
def store_dir
"your_directory/"
end

Now, we generate a model and give it a picture attribute, which will be an image. If you already have a model in your project, you can simply add the attribute to the existing model.

rails generate model Post

Now go to the model file - app/models/post.rb, and add the following lines:

class Post < ApplicationRecord
attr_accessor :picture
mount_uploader :picture, PictureUploader
end

You are free to change the name of the attribute from :picture to something else.

Perform the database migrations. This will add two columns - title, picture to the Posts table of our database.

rails g migration AddPictureToPosts picture:string
rails g migration AddTitleToPosts title:string
rails db:migrate

Now, create another controller named after the model. For example, we'll create a controller called Post.

rails generate controller Posts

Now, go to app/controllers/posts_controller.rb, and add the following methods:

class PostsController < ApplicationController
def index
@posts = Post.all
end
def show
@post = Post.find params[:id]
end
def new
@post = Post.new
end
def create
@post = Post.new post_params
if @post.save
redirect_to @post
else
render 'new'
end
end
def post_params
params.require(:post).permit(:title, :picture)
end
end

Here, we create standard methods to show all posts, show a single post, and create a new post. These methods will have to be accompanied by some HTML markup as well. So go to app/views/posts/, and add the following files

index.html.erb

<%= @posts.each do |post| %>
<div class="post">
<div class="image">
<%= image_tag post.picture.url %>
</div>
<div class="content">
<%= link_to "#{post.title}", post_path(post), class: "header" %>
</div>
</div>
<% end %>
<%= link_to 'Back', posts_path %>

new.html.erb

<%= form_with model: @post do |form| %>
<%= label_tag(:title, "Enter title of post") %>
<%= form.text_field :title %>
<%= label_tag(:picture, "Upload a picture") %>
<%= form.file_field :picture %>
<%= submit_tag "Submit" %>
<% end %>
<%= link_to 'Back', posts_path %>

show.html.erb

<div class="post">
<div class="image">
<%= image_tag @post.picture.url %>
</div>
<div class="content">
<%= link_to "#{@post.title}", post_path(@post), class: "header" %>
</div>
</div>
<%= link_to 'Back', posts_path %>

Now, restart the server and go to http://localhost:3000/posts/new. You should see two form fields, for title, and picture. Enter a text value for the title field, and upload an image/file for the picture field, and click on Submit. This should redirect you to http://localhost:3000/posts/1, displaying the title and the image.

This sums up how you can upload images to your Media Library using the SDK. The second method is more suited for RESTful applications with CRUD operations where the image is an attribute of a resource.

Authentication parameter generation

You can use the SDK to generate authentication parameters that are required if you want to implement client-side upload functionality using javascript or some front-end framework.

# app/controllers/welcome_controller.rb
def auth_params
@auth_params = @imagekitio.get_authentication_parameters()
end
# config/routes.rb
get 'welcome/auth_params'
# app/views/welcome/auth_parameters.html.erb
<div>
<%= @auth_params %>
</div>

The get_authentication_parameters(token = nil, expire = nil) takes two optional arguments, token, and expire. token defaults to a random string if not provided. expire defaults to infinite.

You should see an output like this:

{
:token=>"6b4d79e5-eb36-4de0-8ef5-534c88e45ebf",
:expire=>1600957501,
:signature=>"4c19c4066a140921eddaff7aaa3625df2bf8182a"
}

What's next

The possibilities for image manipulation and optimization with ImageKit are endless. Learn more about it here: