#67 Decoding and Interacting with Barcodes

Summary

Using the QuaggaJS Library, learn how to scan and decode barcodes with your Ruby on Rails application. Using provided callbacks, interact with controller actions to provide a seamless experience.
rails javascript view ajax 11:40

Resources

Summary

# application.css
#barcode-scanner canvas.drawingBuffer, #barcode-scanner video.drawingBuffer {
  display: none;
}

#barcode-scanner canvas, #barcode-scanner video {
  width: 100%;
  height: auto;
}

# application.js
//= require quagga
//= require_tree .

function order_by_occurrence(arr) {
  var counts = {};
  arr.forEach(function(value){
      if(!counts[value]) {
          counts[value] = 0;
      }
      counts[value]++;
  });

  return Object.keys(counts).sort(function(curKey,nextKey) {
      return counts[curKey] < counts[nextKey];
  });
}

function load_quagga(){
  if ($('#barcode-scanner').length > 0 && navigator.mediaDevices && typeof navigator.mediaDevices.getUserMedia === 'function') {

    var last_result = [];
    if (Quagga.initialized == undefined) {
      Quagga.onDetected(function(result) {
        var last_code = result.codeResult.code;
        last_result.push(last_code);
        if (last_result.length > 20) {
          code = order_by_occurrence(last_result)[0];
          last_result = [];
          Quagga.stop();
          $.ajax({
            type: "POST",
            url: '/products/get_barcode',
            data: { upc: code }
          });
        }
      });
    }

    Quagga.init({
      inputStream : {
        name : "Live",
        type : "LiveStream",
        numOfWorkers: navigator.hardwareConcurrency,
        target: document.querySelector('#barcode-scanner')  
      },
      decoder: {
          readers : ['ean_reader','ean_8_reader','code_39_reader','code_39_vin_reader','codabar_reader','upc_reader','upc_e_reader']
      }
    },function(err) {
        if (err) { console.log(err); return }
        Quagga.initialized = true;
        Quagga.start();
    });

  }
};
$(document).on('turbolinks:load', load_quagga);

# visitors/index.html.erb
<div id='barcode-scanner'></div>

# routes.rb
Rails.application.routes.draw do
  resources :products do
    post :get_barcode, on: :collection
  end
  root 'visitors#index'

# rake routes
#               Prefix Verb   URI Pattern                     Controller#Action
# get_barcode_products POST   /products/get_barcode(.:format) products#get_barcode
#             products GET    /products(.:format)             products#index
#                      POST   /products(.:format)             products#create
#          new_product GET    /products/new(.:format)         products#new
#         edit_product GET    /products/:id/edit(.:format)    products#edit
#              product GET    /products/:id(.:format)         products#show
#                      PATCH  /products/:id(.:format)         products#update
#                      PUT    /products/:id(.:format)         products#update
#                      DELETE /products/:id(.:format)         products#destroy
#                 root GET    /                               visitors#index
end

# products_controller.rb
  # GET /products/new
  def new
    @product = Product.new
    @product.upc = params[:upc]
  end

  ...

  # POST /products/get_barcode
  def get_barcode
    @product = Product.find_or_initialize_by(upc: params[:upc])
    unless @product.new_record?
      redirect_to @product
    else
      redirect_to new_product_path(upc: params[:upc])
    end
  end