Serverless File Uploads for Ruby on Rails
Overview
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:

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.
Installation
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
Configuration
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
...
development:
<<: *defaults
test:
<<: *defaults
production:
<<: *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.
Model
When blogging, you make posts. So, our demo app requires a Post
model with
the:
title
attribute of typestring
body
attribute of typetext
file
attribute of typetext
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
end
If we were to go with multi-file uploading, we’d declare has_uploadcare_group
instead.
Views
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>
<html>
<head>
<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 %>
</head>
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>
<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') %>
</div>
<% end %>
<h4 class="card-title"><%= link_to post.title, post_path(post) %></h4>
<p class="card-text"><%= truncate(post.body, length: 150) %></p>
</div>
</div>
</div>
<% end %>
</div>
<% end %>
</div>
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>
</div>
<% if post.file? %>
<div class="image_wrapper">
<%= image_tag post.file %>
</div>
<% end %>
<%= form_for post do |f| %>
<div class="form-group">
<%= f.text_field :title, placeholder: 'Title', class: 'form-control form-control-lg' %>
</div>
<div class="form-group">
<%= f.text_area :body, placeholder: 'The body of your post', class: 'form-control form-control-lg', rows: '3' %>
</div>
<div class="form-group">
<%= f.uploadcare_uploader :file %>
</div>
<%= 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>
</div>
<% if @post.file? %>
<div class="image_wrapper">
<%= image_tag @post.file %>
</div>
<% end %>
<p><%= raw @post.body %></p>
Controller
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
else
@rows << []
@rows[-1] << post
end
end
end
def new
@post = Post.new
end
def create
@post = Post.new(post_params)
if @post.save
redirect_to post_path(@post)
else
render :new
end
end
def destroy
@post.destroy
redirect_to posts_path
end
private
def post_params
params.require(:post).permit(:title, :body, :file)
end
def set_post
@post = Post.find(params[:id])
end
end
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 http://guides.rubyonrails.org/routing.html
resources :posts
root to: 'posts#index'
end
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.
Conclusion
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.