Image Upload Part 2

In part 1, we learned how to set up a simple image upload using Carrierwave and Cloudinary.

Although we are able to upload an image, but it lacks image manipulation functionalities, i.e. cropping.

Let's improve our image upload to allow for cropping!

Usually, this involves JavaScript and fortunately, Cloudinary has a JavaScript library which we could use!

1. Update Cloudinary Settings

For the Cloudinary JavaScript Library to work, we need to allow unsigned uploads in Cloudinary.

Sign in to Cloudinary, proceed to Settings > Upload Tab and scroll to the bottom.

Click on Add upload preset and make sure the mode is Unsigned.

Remember the value of the Name as we'll use it later.

2. Install JavaScript Library

Back to the code, add the following to the head tag of app/views/layouts/application.html.erb:

<script src="//widget.cloudinary.com/global/all.js" type="text/javascript"></script>

3. Add JavaScript Code

Create an empty file app/assets/javascripts/grams.js and add the following:

$(document).on('ready page:load', function() {
  $('.js-gram-image-upload').on('click', function(e) {
    e.preventDefault();

    scope = this;

    cloudinary.openUploadWidget(
      {
        cloud_name: 'jollygoodcode',
        upload_preset: 'your_upload_preset_name',
        cropping: 'server',
        cropping_aspect_ratio: 1,
        cropping_show_dimensions: true,
        form: '#new_gram',
        field_name: 'gram[image]'
      },
      function(error, result) {
        console.log(error, result);
        $(scope).after('<div class="gram-preview"><img src="' + result[0].url + '"></div>');
      }
    );
  });
});

Replace your_upload_preset_name with the value copied from Step 1.

This piece of code basically binds onto an "Upload Image" link and will pop up the Cloudinary JavaScript image upload widget on clicking of the link.

4. Update new.html.erb

Next, we add the link that the JavaScript code in Step 3 binds to.

Notice the use of a special class js-gram-image-upload.

Remove the line:

<%= f.file_field :image %>

Add the line:

<%= link_to 'Upload Image', '#', class: 'js-gram-image-upload' %>

5. New Cloudinary Transformation

At this stage, we can give our image upload a try, and so when you click on the Upload Image link, the Cloudinary JavaScript popup appears and you can crop and upload an image!

However on show.html.erb or index.html.erb, it's not showing the cropped version. We need to do more.

Let's get this new transformation into app/uploades/image_uploader.rb:

  version :cropped do
    cloudinary_transformation(
      transformation:
        [
          { crop: :crop, gravity: :custom },
          { width: 600, height: 600, crop: :fill },
        ]
    )
  end

6. Upload show.html.erb and index.html.erb

Although we added a new version to ImageUploader, it's not used anywhere yet.

So, just update show and index to use the:croppedversion instead of the:standard` version.

For example, in index.html.erb:

<div><%= image_tag @gram.image_url(:cropped) %></div>

In show.html.erb:

<div><%= image_tag @gram.image_url(:cropped) %></div>

Done!

Easy Peasy~