bastengao/highcharts_exporting

View on GitHub
lib/highcharts_exporting/exporter.rb

Summary

Maintainability
A
25 mins
Test Coverage
require 'fileutils'
require 'tempfile'
require 'phantomjs'

# references:
#   http://www.highcharts.com/docs/export-module/export-module-overview
#   https://github.com/highslide-software/highcharts.com/tree/master/exporting-server/phantomjs
module HighchartsExporting
  module Exporter
    def export
      @infile_tmp_file = infile_file

      type = params[:type] || 'image/png'
      extension = MIME::Types[type].first.extensions.first

      @output_tmp_file = Tempfile.new(['output', ".#{extension}"], tmp_dir)
      filename = params[:filename] || 'Chart'
      scale = params[:scale] || 2
      width = params[:width]
      constr = params[:constr] || 'Chart'

      convert_args = convert_args({infile: @infile_tmp_file.path,
                                   outfile: @output_tmp_file.path,
                                   scale: scale,
                                   width: width,
                                   constr: constr,
                                   callback: callback_path
                                  })

      result = ::Phantomjs.run(*convert_args)
      puts result if VERBOSE

      # TODO: clean @output_tmp_file
      @infile_tmp_file.delete
      @callback_tmp_file.delete if @callback_tmp_file

      if /Error/ =~ result
        render text: result, status: 500
      else
        send_file @output_tmp_file.path, filename: "#{filename}.#{extension}", type: type
      end
    end

    protected
    def tmp_dir
      Rails.root.join('tmp/highcharts').to_s.tap { |f| FileUtils.mkdir_p f }
    end

    def infile_file
      tmp_file = nil
      if params[:options]
        tmp_file = Tempfile.new(['options', '.json'], tmp_dir)
        temp_write(tmp_file, params[:options])
      elsif params[:svg]
        tmp_file = Tempfile.new(['options', '.svg'], tmp_dir)
        temp_write(tmp_file, params[:svg])
      end

      tmp_file
    end

    def callback_path
      if params[:callback]
        @callback_tmp_file = Tempfile.new(['callbacks', '.js'], tmp_dir)
        temp_write(@callback_tmp_file, params[:callback])
        @callback_tmp_file.path
      else
        nil
      end
    end

    def convert_args(args)
      convert_args = args.reject { |k, v| v.blank? }.to_a.map { |pair| ["-#{pair[0]}", pair[1].to_s] }.flatten

      convert_args.unshift("--web-security=false", convert_js_path)
    end

    def convert_js_path
      File.join(ROOT, 'phantomjs/highcharts-convert.js').to_s
    end

    def temp_write(tmp_file, content)
      File.open(tmp_file.path, 'r+') do |f|
        f.write content
      end
    end
  end
end