uploadcare-rails is a Rails integration for Uploadcare built on top of the rewritten uploadcare-ruby client API.
The current stable branch is the 5.0 release line.
The gem is centered on:
Uploadcare::Rails.clientfor the default app-level client- explicit
Uploadcare::Clientinstances for multi-account usage has_uploadcare_fileandhas_uploadcare_filesfor model-backed attributesuploadcare_file_fieldanduploadcare_files_fieldfor uploader fieldsActiveStorage::Service::UploadcareServicefor Active Storage integration
This version uses the new Uploadcare File Uploader based on Web Components.
- Requirements
- Installation
- Configuration
- Uploader setup
- Uploader fields
- Model integration
- Attached objects
- Manual API usage
- Multi-account usage
- Active Storage
- Image transformations
- Useful links
- Ruby 3.3+
- Rails 7.2+
Add the gem to your Gemfile:
gem "uploadcare-rails", "~> 5.0"Then install:
bundle installIf your application uses api_struct, replace it with uploadcare-api_struct:
gem "uploadcare-api_struct"You can also install the gem directly:
gem install uploadcare-rails -v 5.0.0Set your Uploadcare credentials with environment variables:
export UPLOADCARE_PUBLIC_KEY=your_public_key
export UPLOADCARE_SECRET_KEY=your_secret_keyGenerate the config file:
rails g uploadcare_configThat creates config/uploadcare.yml.
Typical config/uploadcare.yml:
default: &default
public_key: <%= Rails.application.credentials.dig(:uploadcare, :public_key) %>
secret_key: <%= Rails.application.credentials.dig(:uploadcare, :secret_key) %>
store_files_after_save: true
delete_files_after_destroy: true
store_files_async: false
delete_files_async: false
cache_files: true
cache_expires_in: <%= 1.day.to_i %>
locale: en
development:
<<: *default
test:
<<: *default
production:
<<: *defaultYou can also configure the gem directly in Rails configuration or with the convenience block.
Using config/application.rb:
config.uploadcare.public_key = ENV.fetch("UPLOADCARE_PUBLIC_KEY")
config.uploadcare.secret_key = ENV.fetch("UPLOADCARE_SECRET_KEY")
config.uploadcare.store_files_after_save = false
config.uploadcare.delete_files_after_destroy = trueUsing Uploadcare::Rails.configure:
Uploadcare::Rails.configure do |config|
config.public_key = ENV.fetch("UPLOADCARE_PUBLIC_KEY")
config.secret_key = ENV.fetch("UPLOADCARE_SECRET_KEY")
config.store_files_after_save = false
config.store_files_async = false
config.delete_files_after_destroy = true
config.delete_files_async = false
config.cache_files = true
config.cache_expires_in = 1.hour
config.locale = "en"
endUploadcare::Rails.configure also syncs the default SDK configuration, so the default Rails client and the default SDK client stay aligned.
Add the uploader assets to your layout:
<head>
<%= uploadcare_include_tag %>
</head>That helper emits the stylesheet plus the JavaScript module import that registers the Uploadcare Web Components.
Options:
version:uploader version, default"v1"solution:"regular","inline", or"minimal"min:whether to use minified assets, defaulttrueimportmap:emit only the stylesheet when JavaScript is loaded separately
Example:
<%= uploadcare_include_tag(solution: "inline", version: "v1") %>For Rails apps using importmap-rails:
rails g uploadcare_importmapThen import the initializer:
import "uploadcare"And add the stylesheet to your layout:
<%= uploadcare_stylesheet_tag %>Install the uploader package:
npm install @uploadcare/file-uploaderRegister the Web Components:
import * as UC from "@uploadcare/file-uploader"
UC.defineComponents(UC)Import the stylesheet:
import "@uploadcare/file-uploader/web/uc-file-uploader-regular.min.css"Use uploadcare_file_field for single files:
<%= uploadcare_file_field :post, :picture %>Use uploadcare_files_field for group-backed attributes:
<%= uploadcare_files_field :post, :attachments %>uploadcare_files_field defaults multiple: true and group_output: true, so the submitted value is a single Uploadcare group URL that matches has_uploadcare_files.
Both helpers accept File Uploader configuration options such as:
solution:multiple:img_only:accept:source_list:metadata:
Example:
<%= uploadcare_file_field :post, :picture, solution: "inline", img_only: true %>When you are not binding the uploader to a model object:
<%= uploadcare_file_field_tag :picture %>
<%= uploadcare_files_field_tag :attachments %>form_with and form_for use the same public naming:
<%= form_with model: @post do |f| %>
<%= f.uploadcare_file_field :picture %>
<%= f.uploadcare_files_field :attachments, solution: "inline" %>
<%= f.submit %>
<% end %>Validation errors are wrapped through Rails’ standard field_error_proc.
Use has_uploadcare_file for a single Uploadcare file URL stored in a string column:
class Post < ApplicationRecord
has_uploadcare_file :picture
endUse has_uploadcare_files for a single Uploadcare group URL stored in a string column:
class Post < ApplicationRecord
has_uploadcare_files :attachments
endExample schema:
create_table :posts do |t|
t.string :picture
t.string :attachments
endExample form:
<%= form_with model: @post do |f| %>
<%= f.uploadcare_file_field :picture %>
<%= f.uploadcare_files_field :attachments %>
<%= f.submit %>
<% end %>The model macros add helper methods such as:
uploadcare_store_picture!uploadcare_delete_picture!uploadcare_store_attachments!
You can also enable automatic behavior through configuration:
store_files_after_savestore_files_asyncdelete_files_after_destroydelete_files_async
Model macros accept uploadcare_client: so records can resolve a tenant-specific client:
class Asset < ApplicationRecord
belongs_to :account
has_uploadcare_file :file, uploadcare_client: -> {
Uploadcare::Client.new(
public_key: account.uploadcare_public_key,
secret_key: account.uploadcare_secret_key
)
}
endThat client is used by mounted objects and synchronous model callbacks. Async model callbacks use the default Uploadcare::Rails.client, so tenant-specific uploadcare_client: values should stay synchronous.
Mounted attributes return small wrapper objects that keep Rails-friendly behavior while delegating API work to the client-bound SDK resources.
has_uploadcare_file returns Uploadcare::Rails::AttachedFile.
Example:
post = Post.create!(picture: "https://ucarecdn.com/2d33999d-c74a-4ff9-99ea-abc23496b052/")
post.picture.uuid
post.picture.cdn_url
post.picture.to_s
post.picture.loaded?
post.picture.load
post.picture.store
post.picture.deletehas_uploadcare_files returns Uploadcare::Rails::AttachedFiles.
Example:
post = Post.create!(attachments: "https://ucarecdn.com/dbc4e868-b7a6-43ff-a35f-2ebef935dc1b~2/")
post.attachments.id
post.attachments.files_count
post.attachments.file_urls
post.attachments.loaded?
post.attachments.load
post.attachments.store
post.attachments.deleteThe following utility constants are part of the supported public API:
Uploadcare::Rails::IdExtractor.call("https://ucarecdn.com/<uuid>/")
Uploadcare::Rails::Transformations::ImageTransformations.new(resize: "200x200").callThe Rails gem no longer provides a second API wrapper layer. For manual Uploadcare operations, use Uploadcare::Rails.client or build your own Uploadcare::Client.
client = Uploadcare::Rails.client
file = client.files.find(uuid: "2d33999d-c74a-4ff9-99ea-abc23496b052")
group = client.groups.find(group_id: "dbc4e868-b7a6-43ff-a35f-2ebef935dc1b~2")
project = client.project.current
webhooks = client.webhooks.list
metadata = client.file_metadata.index(uuid: file.uuid)file = File.open("photo.jpg", "rb") do |io|
Uploadcare::Rails.client.uploads.upload(io, store: true)
end
remote_file = Uploadcare::Rails.client.uploads.upload(
"https://example.com/image.jpg",
store: true
)client = Uploadcare::Rails.client
file = client.files.find(uuid: "2d33999d-c74a-4ff9-99ea-abc23496b052")
files = client.files.list(limit: 10)
client.files.batch_store(uuids: [file.uuid])
client.files.batch_delete(uuids: [file.uuid])
group = client.groups.create(uuids: [file.uuid])
client.groups.find(group_id: group.id)Use the raw parity layer when you want endpoint-level control:
client = Uploadcare::Rails.client
result = client.api.rest.files.list(params: { limit: 10 })
upload_result = client.api.upload.files.from_url(source_url: "https://example.com/image.jpg")For multiple Uploadcare projects in the same Rails process, build explicit clients:
primary = Uploadcare::Client.new(public_key: "pk-1", secret_key: "sk-1")
secondary = Uploadcare::Client.new(public_key: "pk-2", secret_key: "sk-2")
primary_file = primary.files.find(uuid: "uuid-1")
secondary_file = secondary.files.find(uuid: "uuid-2")Uploadcare::Rails.client is just the default client for the common single-account case.
You can also build scoped clients from configuration overrides:
tenant_client = Uploadcare::Rails.client(public_key: tenant.public_key, secret_key: tenant.secret_key)Use explicit clients for:
- per-tenant background work
- manual API usage on behalf of different projects
- model-level
uploadcare_client:lambdas - custom service objects
The gem ships with ActiveStorage::Service::UploadcareService.
Example storage.yml:
uploadcare:
service: Uploadcare
public_key: <%= ENV.fetch("UPLOADCARE_PUBLIC_KEY") %>
secret_key: <%= ENV.fetch("UPLOADCARE_SECRET_KEY") %>
public: trueThen configure your environment:
config.active_storage.service = :uploadcarePrivate signed URLs are not supported by UploadcareService; configure the service with public: true.
UploadcareService defaults to public: true; keeping it explicit in storage.yml is recommended.
Active Storage direct uploads (url_for_direct_upload) are not supported by UploadcareService. Use uploadcare_file_field / uploadcare_files_field for direct uploads.
Download and redirect validation use a trusted-host allowlist. This is hostname-based validation and assumes trusted DNS control for those hosts.
The service:
- uploads through
client.uploads.upload - keeps blob-to-Uploadcare UUID mapping in blob metadata
- resolves downloads and URLs through the service client
- supports Uploadcare-backed previews for PDFs
- applies remote image transformations for variants when the blob is stored in Uploadcare
You continue using normal Active Storage APIs in your app:
class User < ApplicationRecord
has_one_attached :avatar
endAttachedFile and AttachedFiles expose transformation helpers that generate Uploadcare CDN URLs.
Single file:
post.picture.transform_url(quality: "better")
post.picture.transform_url(crop: { dimensions: "300x500", coords: "50,50", alignment: "center" })File group:
post.attachments.file_urls
post.attachments.transform_file_urls(quality: "better")See the Uploadcare transformation reference for the available operations:
https://uploadcare.com/docs/transformations/image/
Public utility constants:
Uploadcare::Rails::IdExtractorUploadcare::Rails::Transformations::ImageTransformations