From c6c05085adc9cec178c421cb681f9b7675a37b4d Mon Sep 17 00:00:00 2001 From: Devin Howard Date: Tue, 7 Oct 2014 19:11:55 -0400 Subject: [PATCH] Added phantomjs script to save an image - this doesn't totally work yet, it has a error with famous Added worker process to call the phantomjs script in app/workers Added hook in models/map.rb to call the worker Added calls to map.touch in mappings_controller.rb so it would get triggered correctly - I'm not sure how this will proceed moving forward --- app/controllers/mappings_controller.rb | 10 ++++- app/models/map.rb | 15 ++++++- app/workers/grab_map_screenshot_worker.rb | 10 +++++ script/phantomjs-save-screenshot.js | 54 +++++++++++++++++++++++ 4 files changed, 87 insertions(+), 2 deletions(-) create mode 100644 app/workers/grab_map_screenshot_worker.rb create mode 100755 script/phantomjs-save-screenshot.js diff --git a/app/controllers/mappings_controller.rb b/app/controllers/mappings_controller.rb index 97225fa6..b28c7638 100644 --- a/app/controllers/mappings_controller.rb +++ b/app/controllers/mappings_controller.rb @@ -15,6 +15,8 @@ class MappingsController < ApplicationController def create @mapping = Mapping.new(params[:mapping]) + @mapping.map.touch(:updated_at) + if @mapping.save render json: @mapping, status: :created else @@ -26,6 +28,8 @@ class MappingsController < ApplicationController def update @mapping = Mapping.find(params[:id]) + @mapping.map.touch(:updated_at) + if @mapping.update_attributes(params[:mapping]) head :no_content else @@ -36,8 +40,12 @@ class MappingsController < ApplicationController # DELETE /mappings/1.json def destroy @mapping = Mapping.find(params[:id]) + @map = @mapping.map + @mapping.destroy + @map.touch(:updated_at) + head :no_content end -end \ No newline at end of file +end diff --git a/app/models/map.rb b/app/models/map.rb index 1c3728e1..87fb358d 100644 --- a/app/models/map.rb +++ b/app/models/map.rb @@ -8,6 +8,8 @@ class Map < ActiveRecord::Base has_many :topics, :through => :topicmappings has_many :synapses, :through => :synapsemappings + after_touch :save_screenshot + # This method associates the attribute ":image" with a file attachment has_attached_file :screenshot, :styles => { :thumb => ['188x126#', :png], @@ -76,7 +78,7 @@ class Map < ActiveRecord::Base json[:updated_at] = self.updated_at_str json end - + ##### PERMISSIONS ###### # returns false if user not allowed to 'show' Topic, Synapse, or Map @@ -105,4 +107,15 @@ class Map < ActiveRecord::Base return true end + def save_screenshot + # TODO - this will grab a map every single frickin' time a map is touched + # we need a system to throttle the amount to 1/hour or something like that + # maybe have a flag - last time this map was screenshotted + # don't update if it was less than an hour ago + # except this has the issue of a user updating map 7x, and it only screenshotting after + # the first time. We only want it to screenhsot the 7th time. + # We need to store a timestamp somewhere and do processing every hour, I think. + GrabMapScreenshotWorker.perform_async(self.id) + end + end diff --git a/app/workers/grab_map_screenshot_worker.rb b/app/workers/grab_map_screenshot_worker.rb new file mode 100644 index 00000000..ed9b2709 --- /dev/null +++ b/app/workers/grab_map_screenshot_worker.rb @@ -0,0 +1,10 @@ +# app/workers/grab_map_screenshot_worker.rb +class GrabMapScreenshotWorker + include Sidekiq::Worker + + def perform(map_id) + Phantomjs.run('./script/phantomjs-save-screenshot.js', map_id.to_s) { |line| + puts line + } + end +end diff --git a/script/phantomjs-save-screenshot.js b/script/phantomjs-save-screenshot.js new file mode 100755 index 00000000..9fe0f4c7 --- /dev/null +++ b/script/phantomjs-save-screenshot.js @@ -0,0 +1,54 @@ +//parse arguments passed from command line (or more likely, from rails) +var system = require('system'); +var args = system.args; +if (args.length <= 1) { + phantom.exit(); + throw new Error("no arguments supplied on command line"); +}//if + +//configurable variables - CHANGE ME +var mapID = args[1]; +var url = 'http://localhost:3000/maps/' + mapID; +var width = 400; +var height = 400; +var thumbsDirRelative = 'app/assets/images/map_thumbnails'; + +//set up writing to filesystem +var fs = require('fs'); +var thumbsDirectory = fs.workingDirectory + '/' + thumbsDirRelative; +if (!fs.isDirectory(thumbsDirectory)) { + fs.makeDirectory(thumbsDirectory); +}//if + +//set up page and the area we'll render as a PNG +var page = require('webpage').create(); +page.viewportSize = { + width: width, + height: height +}; +page.clipRect = { + top: 32, + left: 32, + width: width - 32, + height: height - 32 +}; +page.open(url, function (status) { + if (status === 'success') { + //since this isn't evaluateAsync, it should also ensure the asynchronous + //js stuff is loaded too, hopefully? + page.evaluate(function() { + $(document).ready(function(){ + $('.upperLeftUI, .upperRightUI, .mapControls, .infoAndHelp, #barometer_tab, .footer').hide(); + });//document.ready + });//page.evaluate + + //render page into map_thumbnails directory + var filename = thumbsDirectory + '/map' + mapID + '.png'; + page.render(filename, 'PNG'); + + } else { + //failed to load + }//if + + phantom.exit(); +});