Skip to content

How to upload images with imperavi rails

tanraya edited this page Feb 3, 2012 · 6 revisions

Uploading images delegated to your app. You need to add some code into your app to get its done. I'll show you.

First, create images resource:

$ rails g controller images

Then replace auto-generated routes for images resource in routes.rb with this:

resources :images, :only => [:index, :create]

And remove generated views:

$ rm -rf ./app/views/images

For images uploading and processing I use Dragonfly gem so my examples would be using this gem also.

Okay, let's install Dragonfly gem. Add this code into your Gemfile and then run bundle install:

    gem 'dragonfly'
    gem 'dragonfly-minimagick'
    gem 'rack-cache'

and

$ bundle install

Don' forget to add config/initializers/dragonfly.rb with following code:

require 'dragonfly/rails/images'
require 'dragonfly-minimagick'

# Retrieve Dragonfly Rack app
app = Dragonfly::App[:images]

# Configure Dragonfly with mini_magick
Dragonfly[:images].configure_with(:minimagick)

Now we've got installed Dragonfly and we can start to edit our ImagesController. Open controller source and replace with code below:

class ImagesController < ApplicationController
  skip_before_filter :verify_authenticity_token
  respond_to :html, :json

  def index
    @images = Image.scoped

    respond_with @images do |format|
      format.json { render :json => json_images(@images), :layout => false }
    end
  end

  def create
    @image = Image.new(params[:image])

    if @image.save
      render :text => view_context.image_tag(resize_image(@image, 300, 250).url, :alt => '')
    else
      render :json => @image.errors
    end
  end

private

  def json_images(images)
    json_images = []

    images.each do |image|
      json_images << {
        :thumb => resize_image(image, 120, 100).url,
        :image => resize_image(image, 300, 250).url
      }
    end

    json_images
  end

  def resize_image(image, width = 100, height = 100, gravity = :c)
    image.image.process(:resize_and_crop, :width => width, :height => height, :gravity => gravity.to_s)
  end
end

As you can see we have index and create actions. Index action should render list of images in JSON format. And create action should upload image and respond with image tag html or with JSON object with errors if any errors occurs.

Now generate Image model

$ rails g model Image image_uid:string

then run rake db:migrate and then replace Image source with code below:

class Image < ActiveRecord::Base
  ALLOWED_MIME_TYPES = ['image/jpeg', 'image/jpg', 'image/png', 'image/gif']
  ALLOWED_EXTENSIONS = [:jpeg, :jpg, :png, :JPEG, :JPG, :PNG]

  image_accessor :image # accessor to image_uid

  validates :image, :presence => true, :on => :create
  validates :image, :length => { :maximum => 6.megabytes }

  # Dragonfly custom validators for image
  # see: github.com/markevans/dragonfly
  validates_property :format,    :of => :image, :in => ALLOWED_EXTENSIONS
  validates_property :mime_type, :of => :image, :in => ALLOWED_MIME_TYPES
  validates_property :width,     :of => :image, :in => (150..3000)
  validates_property :height,    :of => :image, :in => (150..3000)

  default_scope order(:updated_at)
end

Nothing extraordinary, just standard model with Dragonfly image_accessor method and validators. Now when you call imperavi helper you should pass some options:

<%= imperavi :page_article,
  :paths => {
    :images => {
      # Path to upload handler
      :upload => images_path,

      # Path to list of images
      :list   => images_path(:format => :json)
    }
  }
%>
Clone this wiki locally