#27 WYSIWYG Editor with Summernote

Summary

Integrate Summernote WYSIWYG Editor into your application. Learn how to use AJAX callbacks to filestore your images instead of database Base64.
rails wysiwyg view ajax javascript 7:40

Resources

Summary

# Gemfile
gem 'summernote-rails'
gem "refile", require: "refile/rails"
gem "refile-mini_magick"

Generate a new model for your images to be stored. Without Refile (or a similar uploader), the images will be converted to BASE64 and stored within the database.

# bash
rails g model image image_id image_filename image_size:integer image_content_type

# application.js
//= require summernote

# application.css.scss
/*
@import "bootstrap-sprockets";
@import "bootstrap";
*/
@import "summernote";

# _form.html.erb
    <%= f.input :summary, as: :summernote %>
    <%= f.input :content, as: :summernote %>

# articles.coffee
$ ->
  sendFile = (that, file) ->
    data = new FormData
    data.append 'image[image]', file
    $.ajax
      data: data
      type: 'POST'
      url: '/images'
      cache: false
      contentType: false
      processData: false
      success: (data) ->
        img = document.createElement('IMG')
        img.src = data.url
        img.setAttribute('id', data.image_id)
        $(that).summernote 'insertNode', img

  deleteFile = (file_id) ->
    $.ajax
      type: 'DELETE'
      url: "/images/#{file_id}"
      cache: false
      contentType: false
      processData: false

  ready = ->
    $('[data-provider="summernote"]').each ->
      $(this).summernote 
        height: 200
        callbacks: 
          onImageUpload: (files) ->
            img = sendFile(this, files[0])
          onMediaDelete: (target, editor, editable) ->
            image_id = target[0].id
            if !!image_id
              deleteFile image_id
            target.remove()
  $(document).ready(ready)
  $(document).on('page:load', ready)

# images_controller.rb
class ImagesController < ApplicationController
  protect_from_forgery except: :create
 
  def create
    @image = Image.new(image_params)
    @image.save
 
    respond_to do |format|
      format.json { render :json => { url: Refile.attachment_url(@image, :image), image_id: @image.image_id } }
    end
  end
 
  def destroy
    @image = Image.find_by(image_id: params[:id])
    @image.destroy
    respond_to do |format|
      format.json { render :json => { status: :ok } }
    end
  end
  
  private
 
  def image_params
    params.require(:image).permit(:image)
  end
end

# routes.rb
Rails.application.routes.draw do
  resources :articles
  resources :images, only: [:create, :destroy]
  root to: 'articles#index'
end

# image.rb
class Image < ActiveRecord::Base
  attachment :image
  belongs_to :article
end