Capturing Signatures with Signature Pad

#44 Capturing Signatures with Signature Pad
8/28/2016

Summary

Using the Javascript Library, Signature Pad, learn how to capture user signatures and store them within your Ruby on Rails application.
3
rails javascript view

Summary

application.js.erb//= require signature_pad
signature.jsfunction resizeCanvas(canvas) {
    var ratio =  Math.max(window.devicePixelRatio || 1, 1);
    canvas.width = canvas.offsetWidth * ratio;
    canvas.height = canvas.offsetHeight * ratio;
    canvas.getContext("2d").scale(ratio, ratio);
}

$(document).on('turbolinks:load', function() {
  var canvas = document.querySelector("canvas");
  if (canvas){
    canvas.height = canvas.offsetHeight;
    canvas.width = canvas.offsetWidth;
    window.onresize = resizeCanvas(canvas);
    resizeCanvas(canvas);
    signature_pad = new SignaturePad(canvas);
    $('.signature_pad_clear').click(function() { signature_pad.clear() });
    $('.signature_pad_save').click(function(event) { 
      if (signature_pad.isEmpty()){
        alert('You must sign to accept the Terms and Conditions');
        event.preventDefault();
      } else {
        $('.signature_pad_input').val(signature_pad.toDataURL());
      }
    });
  }
});
application.css.signature_pad {
  width: 700px;
  height: 400px;
  margin: 0 auto;
}

.signature_pad_body canvas {
  width: 100%;
  height: 100%;
  border: dotted #444;
  background: #CCCCCC;
}
application_controller.rbclass ApplicationController < ActionController::Base
  protect_from_forgery with: :exception
  before_action :verify_terms_acceptance 

  private

  def verify_terms_acceptance
    unless user_signed_in? && current_user.document
      redirect_to new_document_path, alert: 'You must first accept terms and conditions before performing any actions.'
    end
  end
end
documents_controller.rbclass DocumentsController < ApplicationController
  before_action :authenticate_user!
  skip_before_action :verify_terms_acceptance

  def new
    @document = current_user.build_document
  end

  def create
    @document = current_user.build_document(document_params)
    @document.signed_on = DateTime.now
    if @document.save
      redirect_to root_url, notice: 'Terms and Conditions accepted.'
    else
      render :new
    end
  end

  private

    def document_params
      params.require(:document).permit(:signature)
    end
end

On controllers and/or specific actions which should not require the user to accept the Terms and Conditions, make sure that you add

controllerskip_before_action :verify_terms_acceptance

Adding this override should also apply to the authentication controllers.

documents/new.html.erb

<%= simple_form_for @document do |f| %>   <%= f.input_field :signature, as: :hidden, class: 'signature_pad_input' %>   <div class="signature_pad text-center">     <div class="signature_pad_body">       <canvas></canvas>     </div>     <div class="signature_pad_footer">       <div class="text-muted">Sign above</div>       <button type="button" class="btn btn-default signature_pad_clear">Clear</button>       <%= f.button :submit, 'Save', class: 'btn btn-success signature_pad_save'  %>     </div>   </div> <% end %>

visitors/private_content.html.erb<%= image_tag current_user.document.signature %>