The ImageKit Rails gem provides seamless integration with Ruby on Rails applications. It includes view helpers for generating responsive image and video tags with transformations, Active Storage service for storing files in ImageKit, and automatic responsive image generation with srcset.
The gem works with all Active Storage features like has_one_attached and has_many_attached, and provides dedicated view helpers (ik_image_tag and ik_video_tag) that handle URL generation, transformations, and responsive images automatically.
For complete API documentation and source code, see the ImageKit Rails gem on GitHub.
Rubydoc references:
Installation
Add the ImageKit Rails gem to your Gemfile:
gem 'imagekitio', gem 'imagekitio-rails'
Run bundle install:
bundle install
Create config/initializers/imagekit.rb with your credentials from the ImageKit dashboard:
Imagekit::Rails.configure do |config| config.url_endpoint = ENV['IMAGEKIT_URL_ENDPOINT'] # https://ik.imagekit.io/your_imagekit_id config.public_key = ENV['IMAGEKIT_PUBLIC_KEY'] config.private_key = ENV['IMAGEKIT_PRIVATE_KEY'] # Optional defaults # config.transformation_position = :query # or :path # config.responsive = true # Enable responsive images by default end
View helpers
The Rails gem provides ik_image_tag and ik_video_tag helpers that work like Rails' built-in image_tag and video_tag but with ImageKit transformations and responsive image support.
Basic image tag
Use ik_image_tag in your views to display images:
<!-- Basic image -->
<%= ik_image_tag("/photo.jpg", alt: "My Photo") %>
<!-- With transformations -->
<%= ik_image_tag("/photo.jpg", transformation: [{ width: 400, height: 300 }], alt: "Resized Photo") %>
<!-- With standard HTML attributes -->
<%= ik_image_tag("/photo.jpg", class: "rounded shadow", alt: "Styled Photo") %>
Image transformations
Apply transformations using the transformation parameter:
<!-- Resize and crop -->
<%= ik_image_tag("/photo.jpg", transformation: [{
width: 400,
height: 300,
crop: "at_max"
}]) %>
<!-- Border and radius -->
<%= ik_image_tag("/photo.jpg", transformation: [{
radius: 20,
border: "3_FF0000"
}]) %>
Chained transformations
Apply multiple transformations in sequence:
<%= ik_image_tag("/photo.jpg", transformation: [
{ width: 400, height: 300, crop: "at_max" },
{ rotation: 90 },
{ blur: 5, grayscale: true }
]) %>
Responsive images
Responsive images with srcset are enabled by default. The helper automatically generates multiple image sizes:
<!-- Automatic responsive images -->
<%= ik_image_tag("/photo.jpg", width: 800, sizes: "(max-width: 600px) 100vw, 800px") %>
<!-- Disable responsive images for specific cases -->
<%= ik_image_tag("/photo.jpg", responsive: false) %>
<!-- Advanced responsive setup with transformations -->
<%= ik_image_tag(@product.featured_image,
width: 800,
sizes: "(max-width: 640px) 100vw, (max-width: 1024px) 50vw, 800px",
transformation: [{ quality: 85, format: "auto" }],
alt: @product.name
) %>
Lazy loading
Images are lazy-loaded by default:
<!-- Default lazy loading -->
<%= ik_image_tag("/photo.jpg") %>
<!-- Eager loading for above-the-fold images -->
<%= ik_image_tag("/hero.jpg", loading: "eager") %>
Video tags
Use ik_video_tag for video content:
<!-- Basic video -->
<%= ik_video_tag("/video.mp4", controls: true) %>
<!-- With transformations -->
<%= ik_video_tag("/video.mp4",
transformation: [{ width: 640, height: 480 }],
controls: true,
autoplay: true,
muted: true
) %>
Overlays
Add text or image overlays to your images:
Text overlay
<%= ik_image_tag("/background.jpg", transformation: [{
overlay: {
type: "text",
text: "Hello World",
transformation: [{
fontSize: 50,
fontColor: "FFFFFF",
fontFamily: "Arial",
typography: "b"
}]
}
}]) %>
Image overlay
<%= ik_image_tag("/background.jpg", transformation: [{
overlay: {
type: "image",
input: "logo.png",
transformation: [{ width: 100, height: 100 }],
position: { x: 10, y: 10 }
}
}]) %>
Watermark example
<%= ik_image_tag("/product.jpg", transformation: [{
overlay: {
type: "image",
input: "watermark.png",
transformation: [{ width: 150, opacity: 70 }],
position: { focus: "bottom_right" }
}
}]) %>
AI transformations
Use ImageKit's AI-powered transformations:
<!-- Background removal -->
<%= ik_image_tag("/photo.jpg", transformation: [{ aiRemoveBackground: true }]) %>
<!-- Upscaling -->
<%= ik_image_tag("/small-photo.jpg", transformation: [{ aiUpscale: true }]) %>
<!-- AI drop shadow -->
<%= ik_image_tag("/logo.png", transformation: [{ aiDropShadow: true }]) %>
Signed URLs
Generate signed URLs for secure content delivery:
<!-- Image with signature that expires in 1 hour -->
<%= ik_image_tag("/private/photo.jpg", signed: true, expires_in: 3600) %>
<!-- Video with signature -->
<%= ik_video_tag("/private/video.mp4", signed: true, expires_in: 3600, controls: true) %>
Active Storage integration
ImageKit integrates seamlessly with Rails Active Storage, allowing you to store attachments in ImageKit while maintaining Active Storage's familiar API.
Configuration
Add ImageKit as a storage service in config/storage.yml:
imagekit: service: ImageKit
Override credentials per environment
By default, the Active Storage service uses credentials from your global configuration (config/initializers/imagekit.rb). You can optionally override these credentials in storage.yml to use different ImageKit accounts for different environments:
# Use global configuration (most common) imagekit: service: ImageKit # Override with environment-specific credentials imagekit_production: service: ImageKit private_key: <%= ENV['IMAGEKIT_PRODUCTION_PRIVATE_KEY'] %> public_key: <%= ENV['IMAGEKIT_PRODUCTION_PUBLIC_KEY'] %> url_endpoint: <%= ENV['IMAGEKIT_PRODUCTION_URL_ENDPOINT'] %> imagekit_staging: service: ImageKit private_key: <%= ENV['IMAGEKIT_STAGING_PRIVATE_KEY'] %> public_key: <%= ENV['IMAGEKIT_STAGING_PUBLIC_KEY'] %> url_endpoint: <%= ENV['IMAGEKIT_STAGING_URL_ENDPOINT'] %>
Then reference the specific service in your environment config:
# config/environments/production.rb config.active_storage.service = :imagekit_production # config/environments/staging.rb config.active_storage.service = :imagekit_staging
Note: If credentials are provided in storage.yml, they take precedence over the global configuration. If not provided, the service falls back to the global configuration.
Set ImageKit as your storage service:
# config/environments/production.rb config.active_storage.service = :imagekit # config/environments/development.rb config.active_storage.service = :local # Keep local storage for development
File attachments
Use Active Storage's attachment methods in your models:
# app/models/user.rb class User < ApplicationRecord has_one_attached :avatar has_many_attached :photos end
# app/models/product.rb class Product < ApplicationRecord has_one_attached :featured_image has_many_attached :gallery_images end
Upload files
Create forms to upload files:
<!-- app/views/users/edit.html.erb -->
<%= form_with model: @user do |form| %>
<div>
<%= form.label :avatar, "Profile Picture" %>
<%= form.file_field :avatar %>
</div>
<%= form.submit "Update Profile" %>
<% end %>
Handle uploads in controllers:
# app/controllers/users_controller.rb
class UsersController < ApplicationController
def update
@user = current_user
if @user.update(user_params)
redirect_to @user, notice: "Profile updated!"
else
render :edit
end
end
private
def user_params
params.require(:user).permit(:name, :avatar)
end
end
Display attachments
Use ik_image_tag with Active Storage attachments:
<!-- User avatar with transformations -->
<%= ik_image_tag(@user.avatar, transformation: [
{ width: 200, height: 200, crop: "at_max" },
{ radius: "max" }
], alt: @user.name) %>
<!-- Product images -->
<% @product.gallery_images.each do |image| %>
<%= ik_image_tag(image, transformation: [
{ width: 400, height: 400, crop: "at_max" },
{ quality: 85 }
]) %>
<% end %>
Getting URLs programmatically
For views, always use ik_image_tag (covered above). However, if you need raw URLs for non-view contexts like APIs, background jobs, mailers, or JSON responses, access the service directly:
# Get URL for an attachment
url = @user.avatar.service.url(@user.avatar.blob.key)
# => "https://ik.imagekit.io/your_id/abc123xyz"
# With transformations
url = @user.avatar.service.url(
@user.avatar.blob.key,
transformation: [{ width: 200, height: 200 }]
)
# => "https://ik.imagekit.io/your_id/abc123xyz?tr=w-200,h-200"
Example: In a JSON API response
# app/controllers/api/users_controller.rb
def show
render json: {
user: {
name: @user.name,
avatar_url: @user.avatar.service.url(
@user.avatar.blob.key,
transformation: [{ width: 150, height: 150, crop: "thumb" }]
)
}
}
end
Example: In a mailer
# app/mailers/user_mailer.rb
class UserMailer < ApplicationMailer
def welcome_email(user)
@avatar_url = user.avatar.service.url(
user.avatar.blob.key,
transformation: [{ width: 100, height: 100 }]
)
mail(to: user.email, subject: "Welcome!")
end
end
Check if file is attached
<% if @user.avatar.attached? %>
<%= ik_image_tag(@user.avatar, transformation: [{ width: 200, height: 200 }]) %>
<% else %>
<%= ik_image_tag("/placeholder.jpg", transformation: [{ width: 200, height: 200 }]) %>
<% end %>
Delete attachments
# In your controller @user.avatar.purge # Delete immediately @user.avatar.purge_later # Delete via background job (recommended)
Direct uploads
Active Storage's DirectUpload feature (client-side uploads) is not supported with ImageKit because ImageKit uses PUT requests while Active Storage uses multipart/form-data POST requests. Files must be uploaded through your Rails server.
Organizing files in folders
ImageKit stores files using their Active Storage keys as complete file paths. Each attachment automatically gets organized based on its model, attribute, and ID.
For example, a user's avatar is stored at a path like /active_storage/attachments/123/avatar-filename.jpg where the key becomes the complete file path in ImageKit.
This organization happens automatically and doesn't require any configuration. If you need custom folder organization, you can customize the Active Storage key generation in your Rails application.
Migrating from Active Storage variants
If you're migrating from local/S3 storage and currently using Active Storage's .variant() method, you should convert them to ImageKit transformations for better performance.
Why avoid variants with ImageKit?
While variants technically work with ImageKit, they're extremely inefficient:
- Downloads the original file from ImageKit to your server
- Processes it on your server (using ImageMagick/libvips)
- Re-uploads the processed version back to ImageKit
This wastes bandwidth, server resources, and time. ImageKit's transformations happen instantly on ImageKit's servers without any round-trips.
Migration examples
Convert your existing variant calls to ik_image_tag with transformations:
<!-- Before: Using variants (slow with ImageKit) -->
<%= image_tag @photo.variant(resize_to_fill: [400, 300]) %>
<%= image_tag @photo.variant(resize_to_limit: [800, 600]) %>
<%= image_tag @avatar.variant(resize_and_pad: [200, 200, background: [255, 255, 255]]) %>
<!-- After: Using ImageKit transformations (instant, no server processing) -->
<%= ik_image_tag(@photo, transformation: [{ width: 400, height: 300, crop: "fill" }]) %>
<%= ik_image_tag(@photo, transformation: [{ width: 800, height: 600 }]) %>
<%= ik_image_tag(@avatar, transformation: [{
width: 200,
height: 200,
crop: "pad_resize",
background: "FFFFFF"
}]) %>
Common variant conversions
| Active Storage Variant | ImageKit Transformation |
|---|---|
resize_to_fill: [w, h] | { width: w, height: h, crop: "fill" } |
resize_to_limit: [w, h] | { width: w, height: h } |
resize_to_fit: [w, h] | { width: w, height: h, crop: "at_max" } |
resize_and_pad: [w, h, background: color] | { width: w, height: h, crop: "pad_resize", background: "RRGGBB" } |
Important notes
- Don't use
.variant()with ImageKit attachments - Always use
ik_image_taginstead ofimage_tagfor ImageKit attachments - ImageKit transformations are applied on-the-fly at the CDN edge
- No server processing or storage needed for transformed images
What's next
- Explore all transformation options.
- Check the ImageKit Rails gem source code for advanced customization.
- For non-Rails projects, see the Ruby SDK documentation.