So you've developed an impressive rails APP that showcases a gallery of images. Its time to unveil it on the worldwide web via Heroku. Image uploads in a local development environment are currently defaulted to local psql. In production environment (Heroku), a cloud storage service stores images.
By popular choice, AWS S3 cloud service would be suitable to host your images. They offer a free plan, but to sign up it requires a credit/debit card. In my experience setting AWS up for image-handling was challenge. If one does not exercise extreme caution; API key and secret will get exposed on Github.
Unscrupulous bots are on the prowl for these credentials to exploit compute resources. Hence raking up a hefty bill.
Since Heroku does not host pictures, Heroku's addon cloud service Cloudinary does. It offers a solution to web application’s entire image management pipeline. Cloudinary offers comprehensive APIs and administration capabilities. It is easy to integrate with any web application, existing or new on Heroku. Cloudinary provides URL and HTTP based APIs. Which helps integrates with any Web development framework.
As opposed to setting up a separate Cloudinary account. By the end of this article, users will upload pictures over your rails app on Heroku. On the back-end, images uploads to or deleted from Cloudinary. Your rails app displays images hosted on Cloudinary via API exchange. The best part is that Cloudinary will not ask for your credit card to sign up for 10GB free storage.
The following assumptions are being made:
Edit your Gemfile, add the following line.
# ./gemfile
gem ‘carrierwave’
gem ‘cloudinary’
Run "run bundle install" to install inserted gems.
Login Herokuapp page and click on the app as illustrated below;
Navigate to "Resources".
Find & select Cloudinary in the search box as illustrated below;
Select "Start Plan" for free usage and click provision.
You are now redirected to the Cloudinary admin page. Notice generated credentials. Copy cloud name, API key, API secret & Environment Variable.
To hide API key and secret, while the resides in Github, we use config variables. First, navigate to settings and click on config vars. Input credentials (CL_ID, CL_key, Cloudinary_URL) as illustrated below;
Create a cloudinary.yml file in your ‘config’ folder. Copy and paste the template into new file. Substitute Cloud_name for actual cloud name found in Cloudinary admin dashboard. This configuration specifies credentials as well as other attributes.
# config/cloudinary.yml
---
development:
cloud_name: cloud_name
api_key: <%= ENV["CL_ID"] %>
api_secret: <%= ENV["CL_KEY"] %>
enhance_image_tag: true
static_file_support: false
production:
cloud_name: cloud_name
api_key: <%= ENV["CL_ID"] %>
api_secret: <%= ENV["CL_KEY"] %>
enhance_image_tag: true
static_file_support: true
test:
cloud_name: cloud_name
api_key: <%= ENV["CL_ID"] %>
api_secret: <%= ENV["CL_KEY"] %>
enhance_image_tag: true
static_file_support: false
Create an initializer cloudinary.rb as below. When rails server starts up, configuration below will take affect.
Cloudinary.config do |config|
config.cloud_name = 'cloud_name'
config.api_key = ENV["CL_ID"]
config.api_secret = ENV["CL_KEY"]
config.secure = true
config.cdn_subdomain = true
end
Assuming you have built the image upload feature (as shown in learn enough tutorial). Setup uploader for Cloudinary as below;
# app/uploader/picture.rb
class PictureUploader < CarrierWave::Uploader::Base
include CarrierWave::MiniMagick
include Cloudinary::CarrierWave
# Specify dimensions for images to resize to for appropriate display fit
version :standard do
process :resize_to_fill => [400, 400, :north]
end
# Cloudinary will be utilized in production (Heroku) while local psql stored us utilized in development and testing environment.
if Rails.env.production?
include Cloudinary::CarrierWave
CarrierWave.configure do |config|
config.cache_storage = :file
end
else
storage :file
end
# Cloudinary public file path to upload and display pictures
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
# Only files with extension jpg jpeg, gif and png will be uploaded
def extension_whitelist
%w[jpg jpeg gif png]
end
end
For image upload forms, emulate the following erb form on front-end view;
# app/views/micropost/_form.html.erb
<%= form_with(model: @post, local: true) do |form| %>
.
.
<span class="picture">
<%= form.file_field :picture, accept: 'image/jpeg,image/gif,image/png' %>
</span>
.
.
<% end %>
For image display, emulate the following erb tag on front-end view;
# app/views/micropost/_feed.html.erb
<% @feeds.each do |p| %>
.
.
<%= image_tag p.picture.url if p.picture? %>
.
.
<% end %>
Now that you are done, push rails app to Heroku and test it.
Check out my Gitbub Repo, to see how it was done.