From d3649f1d26bf4d8e87ed2eb4399c0760e6b9dc7e Mon Sep 17 00:00:00 2001 From: Devin Howard Date: Sat, 26 Mar 2016 11:31:55 +0800 Subject: [PATCH] DRY map exporting with policy_scoping --- app/controllers/maps_controller.rb | 17 +++- app/models/map.rb | 44 ---------- app/services/map_export_service.rb | 84 +++++++++++++++++++ .../maps/{show.xls.erb => export.xls.erb} | 2 +- config/routes.rb | 2 + 5 files changed, 102 insertions(+), 47 deletions(-) create mode 100644 app/services/map_export_service.rb rename app/views/maps/{show.xls.erb => export.xls.erb} (74%) diff --git a/app/controllers/maps_controller.rb b/app/controllers/maps_controller.rb index fa743d93..762f2e99 100644 --- a/app/controllers/maps_controller.rb +++ b/app/controllers/maps_controller.rb @@ -85,11 +85,24 @@ class MapsController < ApplicationController respond_with(@allmappers, @allmappings, @allsynapses, @alltopics, @allmessages, @map) } format.json { render json: @map } - format.csv { send_data @map.to_csv } - format.xls + format.csv { redirect_to :export } + format.xls { redirect_to :export } end end + # GET maps/:id/export + def export + map = Map.find(params[:id]) + authorize map + exporter = MapExportService(current_user, map) + respond_to do |format| + format.json { render json: exporter.json } + format.csv { send_data exporter.csv } + format.xls { @spreadsheet = exporter.xls } + end + end + + # GET maps/:id/contains def contains @map = Map.find(params[:id]) diff --git a/app/models/map.rb b/app/models/map.rb index 9efc278b..d9eb6a18 100644 --- a/app/models/map.rb +++ b/app/models/map.rb @@ -84,50 +84,6 @@ class Map < ActiveRecord::Base json end - def to_spreadsheet - spreadsheet = [] - spreadsheet << ["Topics"] - spreadsheet << ["Id", "Name", "Metacode", "X", "Y", "Description", "Link", "User", "Permission"] - self.topicmappings.each do |mapping| - topic = mapping.mappable - next if topic.nil? - spreadsheet << [ - topic.id, - topic.name, - topic.metacode.name, - mapping.xloc, - mapping.yloc, - topic.desc, - topic.link, - topic.user.name, - topic.permission - ] - end - spreadsheet << [] - spreadsheet << ["Synapses"] - spreadsheet << ["Id", "Description", "Category", "Topic1", "Topic2", "User", "Permission"] - self.synapses.each do |synapse| - spreadsheet << [ - synapse.id, - synapse.desc, - synapse.category, - synapse.node1_id, - synapse.node2_id, - synapse.user.name, - synapse.permission - ] - end - spreadsheet - end - - def to_csv(options = {}) - CSV.generate(options) do |csv| - to_spreadsheet.each do |line| - csv << line - end - end - end - def decode_base64(imgBase64) decoded_data = Base64.decode64(imgBase64) diff --git a/app/services/map_export_service.rb b/app/services/map_export_service.rb new file mode 100644 index 00000000..30b6109a --- /dev/null +++ b/app/services/map_export_service.rb @@ -0,0 +1,84 @@ +class MapExportService < Struct.new(:user, :map) + def json + # marshal_dump turns OpenStruct into a Hash + { + topics: exportable_topics.map(:marshal_dump), + synapses: exportable_synapses.map(:marshal_dump) + } + end + + def csv(options = {}) + CSV.generate(options) do |csv| + to_spreadsheet.each do |line| + csv << line + end + end + end + + def xls + to_spreadsheet + end + + private + + def topic_headings + [:id, :name, :metacode, :x, :y, :description, :link, :user, :permission] + end + def synapse_headings + [:topic1, :topic2, :category, :description, :user, :permission] + end + + def exportable_topics + visible_topics ||= Pundit.policy_scope!(@user, @map.topics) + topic_mappings = Mapping.includes(mappable: [:metacode, :user]) + .where(mappable: visible_topics, map: @map) + topic_mappings.map do |mapping| + topic = mapping.mappable + OpenStruct.new( + id: topic.id, + name: topic.name, + metacode: topic.metacode.name, + x: mapping.xloc, + y: mapping.yloc, + description: topic.desc, + link: topic.link, + user: topic.user.name, + permission: topic.permission + ) + end + end + + def exportable_synapses + visible_synapses = Pundit.policy_scope!(@user, @map.synapses) + visible_synapses.map do |synapse| + OpenStruct.new( + topic1: synapse.node1_id, + topic2: synapse.node2_id, + category: synapse.category, + description: synapse.desc, + user: synapse.user.name, + permission: synapse.permission + ) + end + end + + def to_spreadsheet + spreadsheet = [] + spreadsheet << ["Topics"] + spreadsheet << topic_headings.map(:capitalize) + exportable_topics.each do |topics| + # convert exportable_topics into an array of arrays + topic_headings.map do { |h| topics.send(h) } + end + + spreadsheet << [] + spreadsheet << ["Synapses"] + spreadsheet << synapse_headings.map(:capitalize) + exportable_synapses.each do |synapse| + # convert exportable_synapses into an array of arrays + synapse_headings.map do { |h| synapse.send(h) } + end + + spreadsheet + end +end diff --git a/app/views/maps/show.xls.erb b/app/views/maps/export.xls.erb similarity index 74% rename from app/views/maps/show.xls.erb rename to app/views/maps/export.xls.erb index 2f11a946..7030d501 100644 --- a/app/views/maps/show.xls.erb +++ b/app/views/maps/export.xls.erb @@ -1,5 +1,5 @@ - <% @map.to_spreadsheet.each do |line| %> + <% @spreadsheet.each do |line| %> <% line.each do |field| %> diff --git a/config/routes.rb b/config/routes.rb index cbbc50f2..a9f82d9c 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -36,6 +36,8 @@ Metamaps::Application.routes.draw do get 'topics/:id/relatives', to: 'topics#relatives', as: :relatives resources :maps, except: [:index, :new, :edit] + get 'maps/:id/export', to: 'maps#export' + get 'explore/active', to: 'maps#activemaps' get 'explore/featured', to: 'maps#featuredmaps' get 'explore/mine', to: 'maps#mymaps'
<%= field %>