CarrierWave MiniMagick and Rails 4 Tutorial

In this tutorial we will create the ability to upload an image, resize an image based on any defined pixels and whitelist file extension types to protect our database.

Let’s add the gems to our gemfile:

#image upload
gem 'carrierwave'
gem 'mini_magick'
bundle install


CarrierWave comes with a generator that will create an upload class. You can generate this by running:

rails generate uploader Picture

This will generate the following:
app/uploaders/picture_uploader.rb


# encoding: utf-8

class PictureUploader < CarrierWave::Uploader::Base

  # Include RMagick or MiniMagick support:
  # include CarrierWave::RMagick
  # include CarrierWave::MiniMagick

  # Choose what kind of storage to use for this uploader:
  storage :file
  # 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}/#{model.id}"
  end

  # Provide a default URL as a default if there hasn't been a file uploaded:
  # def default_url
  #   # For Rails 3.1+ asset pipeline compatibility:
  #   # ActionController::Base.helpers.asset_path("fallback/" + [version_name, "default.png"].compact.join('_'))
  #
  #   "/images/fallback/" + [version_name, "default.png"].compact.join('_')
  # end

  # Process files as they are uploaded:
  # process :scale => [200, 300]
  #
  # def scale(width, height)
  #   # do something
  # end

  # Create different versions of your uploaded files:
  # version :thumb do
  #   process :resize_to_fit => [50, 50]
  # 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

  # Override the filename of the uploaded files:
  # Avoid using model.id or version_name here, see uploader/store.rb for details.
  # def filename
  #   "something.jpg" if original_filename
  # end

end

Uncomment out the following so it looks like this:

# encoding: utf-8

class PictureUploader < CarrierWave::Uploader::Base

  # Include RMagick or MiniMagick support:
  # include CarrierWave::RMagick
  include CarrierWave::MiniMagick

  # Choose what kind of storage to use for this uploader:
  storage :file
  # 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}/#{model.id}"
  end

  # Provide a default URL as a default if there hasn't been a file uploaded:
  # def default_url
  #   # For Rails 3.1+ asset pipeline compatibility:
  #   # ActionController::Base.helpers.asset_path("fallback/" + [version_name, "default.png"].compact.join('_'))
  #
  #   "/images/fallback/" + [version_name, "default.png"].compact.join('_')
  # end

  # Process files as they are uploaded:
  # process :scale => [200, 300]
  #
  # def scale(width, height)
  #   # do something
  # end

  # Create different versions of your uploaded files:
  version :thumb do
    process :resize_to_fit => [50, 50]
  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

  # Override the filename of the uploaded files:
  # Avoid using model.id or version_name here, see uploader/store.rb for details.
  # def filename
  #   "something.jpg" if original_filename
  # end

end

Here we have done a few things, we have enabled MiniMagic, we have created a thumb version of the image and we have white labeled image extension types.

Lets create a migration for pictures in Post:

rails g migration add_picture_to_posts picture:string

run

rake db:migrate

Next, we need to add this to the Post class:


class Post < ActiveRecord::Base
  validates :title, presence: true
  validates :body, presence: true
   mount_uploader :picture, PictureUploader
end

Let’s add this to our post#new view:


=form_for @post do |f| 
	= render "shared/error_messages", target: @post
	=f.label :title 
	=f.text_field :title, required: true 
	=f.label :body
	=f.text_area :body, required: true  
	=f.file_field :picture, required: true
	=f.submit class: "btn"

To view the image on the post, add this to post#view


%h1=@post.title
%p=@post.body
=image_tag @post.picture_url(:thumb)

Now we have an image uploader. Great.

A big thanks to Railscasts for this CarrierWave and RMagick tutorial: http://railscasts.com/episodes/253-carrierwave-file-uploads.

Leave a Reply