15: Using attachments for images
If you have a website where people can post stories, useful advice or other textual stuff, it is very likely that soon they will want to have the possibility to attach some pictures to their posts.
There are a couple of things that we have to think about when planning to add images to our cases, mainly how to upload and how to store them. Fortunately there are services that can handle this for us.
Today we are going to use Cloudinary, a CDN (content delivery network) for working with images, which integrates nicely with Ruby on Rails.
Configuring Cloudinary
So let us start out by creating a Cloudinary account. Go to http://cloudinary.com, and sign up.
Now you can login into Cloudinary and access your dashboard at https://cloudinary.com/console where you can find information about your account, as well as the secret keys that your app should use in order to access the service.
To make our app work with Cloudinary, we need to perform the following things:
- Add a line to the
Gemfile
in the root of your project:gem 'cloudinary'
- Bundle your gems by running in the terminal in the folder of your project:
$ bundle install
- Download the
cloudinary.yml
configuration file. You can do it also by navigating to your Cloudinary Dashboard and clicking the littleYML
link in the image below or following https://cloudinary.com/console/cloudinary.yml:
- Move this file to the
config/
folder of your project.
At this point, we can use the cl_image_tag
helper in our views in order to reference images hosted on Cloudinary.
Configuring Attachinary
However, we still lack the upload functionality. We will use another gem, called attachinary for managing our uploads and attachments.
There is a little bit more work to put in configuring this gem:
- Add the this line to the
Gemfile
(you can put it near the 'cloudinary' gem):gem 'attachinary'
Bundle the gems once again:
$ bundle install
Open the
config/application.rb
file and insert just after the line withrequire 'rails/all'
the following:require 'attachinary/orm/active_record'
- Configure the database for attachments by runing these rake tasks:
$ rake attachinary:install:migrations $ rake db:migrate
- In the
config/routes.rb
file, just afterRails.application.routes.draw do
insert:mount Attachinary::Engine => '/attachinary'
- In the
views/layouts/application.html.erb
, before<%= csrf_meta_tags %>
insert:<%= cloudinary_js_config %>
- At last, in the
app/assets/javascripts/application.js
file, insert these just before//= require turbolinks
://= require cloudinary/jquery.cloudinary //= require attachinary
Adding pictures to posts
Now that we have configured the gems and have run the necessary migrations, we can add a picture to our post with just one line of code. Suppose we have a Case model in the file app/models/case.rb
which looks like this:
class Case < ActiveRecord::Base
belongs_to :user
end
In order to add an image to it, add a line that declares an attachment with the specified name:
class Case < ActiveRecord::Base
has_attachment :case_image
belongs_to :user
end
Our model is ready to accept images as attachments, but we didn't provide the appropriate upload button in the form for creating a new post. Let's do it now:
Open the file app/views/cases/new.html.erb
and insert before <%= form.button :submit %>
(the submit button), a button for uploading images:
<%= form.attachinary_file_field :case_image %>
There is still one thing to do until we can enjoy the fun of uploading pictures to our site. We have to display them to the user.
As noted above, in order to display an image from Cloudinary we have to use the cl_image_tag
helper instead of the standard image_tag
.
In app/views/cases/index.html.erb
, find the line that states:
<%= image_tag(c.image_link, width: 600 ) %>
And replace it with the new one:
<%= cl_image_tag(c.case_image.path, width: 600) %>
Congratulations! Your users can now attach images to their posts!
However, if we start the server, then try to load the cases page (by going to http://localhost:3000/cases
, we see the following:
This is because none of our previous cases do not have an image property, since the images were provided as a link, but not an upload.
The easiest way is to remove all the previous posts. Open the Rails console (rails console
), and type:
Case.destroy_all
We deleted all the content and we have to make new cases now.
Refresh the page, click your version of "Create a new case" link, click Choose file, upload a photo and you should see it on the page.