Serverless File Uploads for Ruby on Rails

19 Minutes to Integrate


This guide will walk you through the process of creating a simple blogging application in Ruby on Rails powered by Uploadcare for uploading images and generating previews.

It will take you about 19 minutes to get a fully functional web app that accepts image uploads for blog posts.

Here is a screenshot of what we are going to build:

Demo Blog Screen Capture

Setting Things Up

Uploadcare Account Keys

The first thing to get you started is an Uploadcare account. So Sign Up if you haven’t done so before. Create a new project on your dashboard or navigate to an existing one; go to the “API Keys” section and find your keys.


Let’s create our demo application and add the Uploadcare integration:

rails new uc-demo-blog -T

Note, the -T flag tells Rails to generate the new application without the default test suite; we’ll skip the suite for this guide.

Executing the command creates a Rails application in the uc-demo-blog directory and installs the dependencies mentioned in your Gemfile. Now, switch to your new app’s directory:

cd uc-demo-blog

Next, integrate Uploadcare. Open your Gemfile and add the following line:

gem 'uploadcare-rails'

The last step left here is running install:

bundle install


In Ruby on Rails, you use the uploadcare.yml file to configure your Uploadcare integration. Run the command below to generate it or create the file manually in your project’s config directory:

bundle exec rails g uploadcare_config

Here’s an example of how your uploadcare.yml may look like:

defaults: &defaults
  public_key: "YOUR_PUBLIC_KEY"
  secret_key: "YOUR_SECRET_KEY"

  # instances of file uploader initialized for you on page load
  live: true

  # cache files json dumps to prevent calling to server if it posible
  cache_files: true

  # cache groups json dumps to prevent calling to server if it posible
  cache_groups: true

  # store file or group after model is created or updated
  store_after_save: true

  # deletes file or group after model object is deleted
  delete_after_destroy: true


  <<: *defaults

  <<: *defaults

  <<: *defaults```

The config won’t be valid unless you set the public_key and secret_key params to your account Public and Secret API Keys respectively.

Creating the Demo Application

Now, let’s enhance our app by adding a data model, views, and a controller. We’ll briefly go over the major points, to dig deep see this demo sources.


When blogging, you make posts. So, our demo app requires a Post model with the:

  • title attribute of type string
  • body attribute of type text
  • file attribute of type text

Let’s generate the model and migrate your database:

rails g model Post title:string body:text
rails db:migrate

Now, we need to handle single-file uploads; update the Post model you just generated to look like this:

class Post < ApplicationRecord
  has_uploadcare_file :file

If we were to go with multi-file uploads, we’d declare has_uploadcare_group instead.


Great, we can now focus on views. If you want to learn more about the Bootstrap components we use, refer to Bootstrap documentation.

To handle uploads, we’ll integrate File Uploader, a file uploader that allows picking files, defining upload sources, previewing, cropping and otherwise editing images.

To get the file uploader from Uploadcare CDN and include application-wide settings put the following in the <head> of application layout:

<!-- app/views/layouts/application.html.erb -->

<!DOCTYPE html>
    <title>Demo Blog</title>
    <%= csrf_meta_tags %>

    <%= stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track': 'reload' %>
    <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>

    <%# Include and config uploadcare file uploader %>
    <%= include_uploadcare_widget_from_cdn version: "3.x", min: true %>
    <%= uploadcare_settings %>

Now let’s see how we can use the Uploadcare gem in views. Let’s use our index view to display all posts:

<!-- app/views/posts/index.html.erb -->

<div class="jumbotron">
  <h1 class="display-2">Recent Posts</h1>
<div class="posts-grid">
  <% @rows.each do |row| %>
    <div class="row">
    <% row.each do |post| %>
      <div class="col-md-4 col-sm-12">
        <div class="card" style="width: 20rem;">
          <div class="card-body">
            <% if post.file? %>
              <div class="image_wrapper">
                <%= image_tag post.file.url(preview: '150x150') %>
            <% end %>
            <h4 class="card-title"><%= link_to post.title, post_path(post) %></h4>
            <p class="card-text"><%= truncate(post.body, length: 150) %></p>
    <% end %>
  <% end %>

There is couple of things going on here. First, we use post.file.url, which is a CDN URL, to display a hosted image within our image_wrapper block. Secondly, we pass the preview argument so that listed posts feature an image thumbnail.

Likewise, add a new view for creating new posts:

<!-- app/views/posts/new.html.erb -->

<div class="jumbotron">
  <h1 class="display-3">Add Post</h1>
<% if post.file? %>
  <div class="image_wrapper">
    <%= image_tag post.file %>
<% end %>
<%= form_for post do |f| %>
  <div class="form-group">
    <%= f.text_field :title, placeholder: 'Title', class: 'form-control form-control-lg' %>
  <div class="form-group">
    <%= f.text_area :body, placeholder: 'The body of your post', class: 'form-control form-control-lg', rows: '3' %>
  <div class="form-group">
    <%= f.uploadcare_uploader :file %>
  <%= f.submit 'Add Post', class: 'btn btn-primary btn-lg'%>
<% end %>

And a view named show to show a created post after form submission:

<!-- app/views/posts/show.html.erb -->

<div class="jumbotron">
  <h1 class="display-3"><%= @post.title %></h1>
<% if @post.file? %>
  <div class="image_wrapper">
    <%= image_tag @post.file %>
<% end %>
<p><%= raw @post.body %></p>


So far so good. Time to add a controller. Let us generate that:

rails g controller Posts

Edit your PostsController to look like below:

class PostsController < ApplicationController
  before_action :set_post, only: [:destroy]

  def index
    @posts = Post.order('created_at')
    @rows = [[]]
    @posts.each do |post|
      if @rows[-1].length < 3
        @rows[-1] << post
        @rows << []
        @rows[-1] << post

  def new
    @post =

  def create
    @post =
      redirect_to post_path(@post)
      render :new

  def destroy
    redirect_to posts_path


  def post_params
    params.require(:post).permit(:title, :body, :file)

  def set_post
    @post = Post.find(params[:id])


We added a few actions here:

  • Listing posts in order of creation
  • Creating and saving a post
  • Deleting a post

As a final step, configure your route file to point to your controller:

# config/routes.rb

Rails.application.routes.draw do
  # For details on the DSL available within this file, see
  resources :posts
  root to: 'posts#index'

That’s it! You can fire up your rails server and point your browser to http://localhost:3000. You should now be able to play with your app: see posts listed on the home page, add new posts, etc.


In this guide, we’ve covered the basics of how to easily integrate file uploading in your Rails application with Uploadcare. If you want to learn more about Uploadcare in Ruby on Rails, check out this Github repo.