Students Save 30%! Learn & create with unlimited courses & creative assets Students Save 30%! Save Now
  1. Code
  2. Ruby

Rails Image Upload: Using CarrierWave and Devise


In the first part of this series, you learned how to use CarrierWave in your Rails application. In this second part, you will learn how to enable image uploading for your users using Devise. Devise is an authentication solution for Rails. You will also learn how to use fog, a Ruby cloud service library that will enable your application to connect to Amazon Web Services.

Enough talk—let’s get down to business.

Rails Application Setup

Generate your new rails application:

rails rails new myapp

Open up your Gemfile and add the following gems:

```rails Gemfile

gem carrierwave gem devise gem mini_magick gem fog ```

Run bundle install to install the gems.

From your terminal, create a Pages controller:

rails rails g controller Pages index

Navigate to config/routes.rb and add a root path:

```rails config/routes.rb

root to: ‘pages#index’ ```

Generate and Configure Devise

The uploading feature will be integrated into our User model for users to upload avatars. From your terminal, install devise:

rails rails generate devise:install

The generator will install an initializer which describes all of Devise’s configuration options. Open up app/views/layouts/application.html.erb in your text editor and add the following code above the yield block:

```rails app/views/layouts/application.html.erb

<%= notice %>

<%= alert %>


At this point you can generate your User model:

rails rails generate devise User

Next, migrate your database:

rails rake db:migrate

You will need to edit devise views, so it is important you generate those:

rails rails generate devise:views

And that will do the magic.

Using your text editor, open app/views/devise/registrations/new.html.erb and edit it to look like this:

```rails app/views/devise/registrations/new.html.erb

Sign up

<%= form_for(resource, as: resource_name, url: registration_path(resource_name), :html => {multipart: :true}) do |f| %> <%= devise_error_messages! %>

<%= f.label :email %>
<%= f.email_field :email, autofocus: true %>
<%= f.label :password %> <% if @minimum_password_length %> (<%= @minimum_password_length %> characters minimum) <% end %>
<%= f.password_field :password, autocomplete: "off" %>
<%= f.label :password_confirmation %>
<%= f.password_field :password_confirmation, autocomplete: "off" %>
<%= f.label :avatar do %> <%= f.file_field :avatar %> <%= f.hidden_field :avatar_cache %> <% end %>
<%= f.submit "Sign up" %>

<% end %>

<%= render “devise/shared/links” %> ```

Do the same for app/views/devise/registrations/edit.html.erb:

```rails app/views/devise/registrations/edit.html.erb

Edit <%= resource_name.to_s.humanize %>

<%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put, multipart: :true }) do |f| %> <%= devise_error_messages! %>

<%= f.label :email %>
<%= f.email_field :email, autofocus: true %>

<% if devise_mapping.confirmable? && resource.pending_reconfirmation? %> <div>Currently waiting confirmation for: <%= resource.unconfirmed_email %></div> <% end %>

<%= f.label :password %> (leave blank if you don't want to change it)
<%= f.password_field :password, autocomplete: "off" %>
<%= f.label :password_confirmation %>
<%= f.password_field :password_confirmation, autocomplete: "off" %>

<% if current_user.avatar.url.present? %> <%= image_tag(current_user.avatar.url) %> <%= f.label :remove_avatar do %> <%= f.check_box :remove_avatar %> <% end %> <% end %> <%= f.file_field :avatar %> <%= f.hidden_field :avatar_cache %>

<%= f.label :current_password %> (we need your current password to confirm your changes)
<%= f.password_field :current_password, autocomplete: "off" %>
<%= f.submit "Update" %>

<% end %>

Cancel my account

Unhappy? <%= button_to "Cancel my account", registration_path(resource_name), data: { confirm: "Are you sure?" }, method: :delete %>

<%= link_to “Back”, :back %> ```

With that done, you will need to whitelist avatar for devise and add an avatar column to the User table. From your terminal, run migration to add a new avatar column.


rails g migration add_avatar_to_users avatar:string rake db:migrate ```

Add the CarrierWave avatar to your User model—your model should look like this:

```rails models/user.rb

class User < ActiveRecord::Base mount_uploader :avatar, AvatarUploader

devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable

# User Avatar Validation validates_integrity_of :avatar validates_processing_of :avatar

private def avatar_size_validation errors[:avatar] « “should be less than 500KB” if avatar.size > 0.5.megabytes end end ```

In the above code, you added a mount_uploader line at the top of the User class. There is also a validation to check the integrity and processing of the avatar, alongside a method to ensure that no image greater than 500KB is uploaded.

You need to add avatar, avatar_cache, and remove_avatar to the list of accessible attributes. Doing this is easy—just open up your application_controller.rb and make it look like this:

```rails app/controllers/application_controller.rb

class ApplicationController < ActionController::Base # Prevent CSRF attacks by raising an exception. # For APIs, you may want to use :null_session instead. protect_from_forgery with: :exception

before_action :configure_permitted_parameters, if: :devise_controller?


def configure_permitted_parameters devise_parameter_sanitizer.for(:sign_up) { |u| u.permit(:username, :email, :password, :password_confirmation, :remember_me, :avatar, :avatar_cache) } devise_parameter_sanitizer.for(:account_update) { |u| u.permit(:username, :password, :password_confirmation, :current_password, :avatar, :avatar_cache, :remove_avatar) } end end ```

With that done, you are ready to integrate CarrierWave.

Setting Up CarrierWave

Using your text editor, navigate to config/initializers and create a file named carrier_wave.rb. Paste in the code below:

rails ***config/initializers/carrier_wave.rb***

rails require 'carrierwave/orm/activerecord'

This is the initializer that is needed in loading CarrierWave after ActiveRecord.

From your terminal, generate an uploader:

rails rails generate uploader Avatar

This will create a new directory called uploaders in the app folder and a file inside called avatar_uploader.rb. I have edited the contents of the file to look like what I have below:



encoding: utf-8

class AvatarUploader < CarrierWave::Uploader::Base

include CarrierWave::MiniMagick

# Choose what kind of storage to use for this uploader: storage :fog

# Override the directory where uploaded files will be stored. # This is a sensible default for uploaders that are meant to be mounted: def store_dir “uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{}” end

# Create different versions of your uploaded files: version :thumb do process :resize_to_fill => [100, 100] end

version :medium do process :resize_to_fill => [300, 300] end

version :small do process :resize_to_fill => [140, 140] end

# Add a white list of extensions which are allowed to be uploaded. # For images you might use something like this: def extension_white_list %w(jpg jpeg gif png) end end ```

You need the MiniMagick line to generate different versions of an image. I included three versions of images. MiniMagick makes the resizing into this version possible. The last code block ensures that no file extensions aside from those listed here are uploaded.

AWS Setup

For this tutorial, we will be uploading our images to Amazon Web Services. If you do not have an account yet, hop over to the sign-up page and create a free account.

When you’ve finished with that, you will need to create a bucket to store your images. When there, choose Create Bucket to open the dialog box. Enter a name for the bucket and select a region. When done, select Create.

Open your Gemfile and add this gem, and bundle install when done.

rails gem 'figaro'

From your terminal, run bundle exec figaro install. This will a create a new file config/application.yml and append it to your application’s .gitignore. You need this file to keep your AWS access id and secret key safe.

To find your AWS access id and secret key, go to Amazon Web Services and click on the name of your account, which is located in the right corner of the console.

From the drop-down, select Security Credentials, and click the Continue to Security Credentials button. In the page that shows, select Access Keys (Access Key ID and Secret Access Key). Click on the Create New Access Key button to generate a new key, and copy it into an editor.

In your text editor, navigate to config/application.yml and paste in the following:

```rails config/application.yml

aws_access_id: Enter access_id here aws_access_secret_key: Enter access_key here ```

Replace the lines as stated above.

Navigate to config/initializers, create a file named storage.rb, and paste in the following:

```rails config/initializers/storage.rb

CarrierWave.configure do |config| = :fog config.fog_credentials = { provider: ‘AWS’, aws_access_key_id: ENV[“aws_access_id”], aws_secret_access_key: ENV[“aws_access_secret_key”], region: ‘us-west-2’ } config.fog_directory = “tutsplus-avatar” config.fog_public = false end ```

According to the above config, the region for my bucket is us-west-2, and the bucket’s name is tutsplus-avatar. Replace that with information about your bucket.

Start up your rails server and point your browser to http://localhost:3000/users/sign_up.

Setting a Default Avatar

In your application, you might want to set a default avatar for users that choose not to upload an avatar. Doing this is easy.

Create a folder in app/assets/images called fallback and drop your default image in it. Using your text editor, navigate to app/uploaders/avatar_uploader.rb and paste in the code below:

```rails app/uploaders/avatar_uploader.rb

def default_url(*args) ActionController::Base.helpers.asset_path(“fallback/” + [version_name, “default-avatar.gif”].compact.join(‘_’)) end ```

Be sure to change default-avatar.gif to the name of your image.


Now you know how to enable image uploading for your users. This adds an important feature to your rails application. I hope you had fun. In the next part, we will have a look at PaperClip. Your feedback is welcome.

Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.