Rails jQuery Ajax Upload Image

Easy Implementation

There are a lot of library for this.
The goal is to realize drag and drop image and update model as binary.

Model

book

class CreateBooks < ActiveRecord::Migration
  def change
    create_table :books do |t|
      t.string :ename, null: false    # English name 
      t.string :cname, null: false    # Chinese name
      t.string :uuid, null: false     # UUID
      t.binary :photo                 # Image
      
      t.timestamps
    end
    
    add_index :books, :ename
    
  end
end

photo is for image(binary)
Model class has no implementation for photo

Route

Add route for upload image
routes.rb

Rails.application.routes.draw do
  resources :books
  post 'books/upload' => 'books#upload'
end

Controller

Create action to receive image and save in model

class BooksController < ApplicationController
  def upload
    file = params[:file]
    name = file.original_filename
    # permit index
    perms = ['.jpg', '.jpeg', '.gif', '.png']
    if !file.nil?
      if !perms.include?(File.extname(name).downcase)
        result = 'You can upload only image'
      elsif file.size > 1.megabyte
        result = 'File size should be up to 1MB'
      else
        book = Book.find(params[:key])
        # Upload
        book.photo = file.read
        book.save
        result = 'Success'
      end
    else
      result = 'File is nil'
    end
    render text: result
  end

  def get_image
      logger.info(params[:id])
      @book = Book.find(params[:id])
      send_data(@book.photo, :disposition => "inline", :type => "image/png")
  end
end

upload action is to upload image.
get_image is to show image in view.

View

Create space for drag and drop

<div id="draggable" book_id="<%= book.id %>">
<% if book.photo.present?  %>
<%= image_tag(url_for(:action => 'get_image', :id => book.id), :size => '120x120')%>
<% else %>
<%= image_tag 'blankimage.png' %>
<% end %>
</div>

Show drag and drop image example is here

JavaScript(CoffeeScript)

Finally, about javascript.
Implement drag and drop and

$ ->
  el = $("#draggable");
  el.on 'drop', (e) ->  
    e.preventDefault()
    console.log("File")
    files = e.originalEvent.dataTransfer.files
    reader = new FileReader()
    file = files[0]
    uploadfile(file, parseInt($(el).attr('book_id')))
    return
  return

$(document).on 'dragover', (e) ->
  e.stopPropagation()
  e.preventDefault()
  return
  
$(document).on 'drop', (e) ->
  e.stopPropagation()
  e.preventDefault()
  console.log("Document")
  return

uploadfile = (file, number) ->
  
  form = new FormData
  form.append('file', file)
  
  $.ajax({
    type: 'POST',
    url: 'books/upload?key=' + number,
    contentType: 'json',
    data: form,
    processData: false,
    contentType: false,
    success: (result) ->
      alert result
      return
    error: ->
      alert 'Fail'
      return
  })
  return