Pictures

Goals

  • What's a dog website without cute pictures? In this lesson you will learn to use gems to enable pictures on your website.

  • We will use the storage service Cloudinary and the image-modification gem CarrierWave to implement the most important part of a shelter website -- cute pictures!

Steps

Step 1

Edit your Gemfile and add the line:

gem 'carrierwave'

Explanation

This gem comes with built-in abilities to process, resize, and store images. When we configure this, we'll have a choice of whether our pictures are stored on our filesystem or in a cloud storage system.

Step 2

Type this in the terminal:
heroku addons:add cloudinary

Heroku might ask you to enter a credit card at this step; Cloudinary's starter plan is free and you will not be charged.

Edit your Gemfile and add the line:

gem 'cloudinary'

Explanation

Since Heroku doesn't let us store images on our filesystem, we will need to use cloud storage. Cloudinary will give us a place to store our images where they'll be accessible via Heroku.

heroku addons:add cloudinary activates Cloudinary via your Heroku account.

Step 3

Type this in the terminal:
bundle install

Explanation

This step installs the carrierwave and cloudinary gems to your application.

Type this in the terminal:
rails g uploader picture

Explanation

rails g is short for rails generate (you can type either; they do the same thing). You may remember this from rails g migration or rails g scaffold -- a generator creates code files for you with some things pre-filled in.

The uploader generator was added to your app by the carrierwave gem; it generated the file app/uploaders/picture_uploader.rb, which you can now open to edit the configuration of your picture upload system.

Step 4

Open app/uploaders/picture_uploader.rb:

Add the code

    include Cloudinary::CarrierWave

under the line class PictureUploader < CarrierWave::Uploader::Base

Explanation

This line tells the uploader to include some code from the cloudinary gem which enables CarrierWave to use Cloudinary as a storage system.

Step 5

comment out this line:

# storage :file

comment out these lines:

# def store_dir
#  "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
#  end

Explanation

If we were storing the pictures on our own filesystem, rather than in the cloud, we would want to keep these lines, and our pictures would be stored in the uploads/ directory; however, since we're going to use Cloudinary instead, we'll need to comment out the lines about filesystem storage.

uncomment the line

 version :thumb

Explanation

This line means the uploader will automatically create resized thumbnail versions of your pictures -- so that your users won't have to worry about what size their pictures are when they upload them.

Step 6

open app/models/dog.rb

add the code:

mount_uploader :picture, PictureUploader

under the line

class Dog < ActiveRecord::Base
Type this in the terminal:
rails g migration add_picture_to_dogs picture:string
Type this in the terminal:
bundle exec rake db:migrate

Step 7

open app/controllers/dogs_controller.rb

Change the line in dog_params to:

require(:dog).permit(:name, :age, :picture)

Explanation

Like when you added age to your dogs, you will need to specify in your controller that users are allowed to modify the dog's picture

If you added any fields to your dogs table before besides name and age, make sure to keep those in the permit arguments so that they will keep working.

Step 8

open app/views/dogs/_form.html.erb and, above one of the other lines saying <div class="field">, add:

   <div class="field">
    <%= f.label :picture %>
    <%= f.hidden_field(:picture_cache) %>
    <%= f.file_field(:picture) %>
  </div>

Explanation

This adds a file upload field to the form where you create or edit dogs, so that you will be able to add a picture.

Step 9

Open app/views/dogs/index.html.erb and add:

    <td>
          <%= image_tag(dog.picture_url(:thumb))  unless dog.picture_url(:thumb).blank? %>
        </td>

Explanation

This line adds an image tag to your HTML, which looks for the URL to the thumbnail picture of your dog and uses that as the image source.

Adding unless dog.picture_url(:thumb).blank? will keep your app from trying to display broken images for any dogs that haven't had pictures uploaded for them.

Step 10

Add cloudinary.yml to your /config folder.

If you are logged in to Heroku in your browser, you should be able to download it from http://cloudinary.com/console/cloudinary.yml.

Save this file to the /config folder under your app's main folder.

The contents of cloudinary.yml should look something like this:

---
development:
  cloud_name: [something]
  api_key: [something]
  api_secret: [something]
  enhance_image_tag: true
  static_image_support: false
production:
  cloud_name: [something]
  api_key: [something]
  api_secret: [something]
  enhance_image_tag: true
  static_image_support: true
test:
  cloud_name: [something]
  api_key: [something]
  api_secret: [something]
  enhance_image_tag: true
  static_image_support: false

Step 11

Commit your changes and push to heroku:

Type this in the terminal:
git commit -a -m "added pictures to dogs"
Type this in the terminal:
git push heroku master
Type this in the terminal:
heroku run rake db:migrate

And now, you should be able to open your Heroku application, upload a picture to your dogs, and see that picture displayed in your list of dogs!

Try exchanging Heroku URLs with other students in your group and uploading dog pictures to each others' apps.

Next Step: