myGrid/taverna-player

View on GitHub
lib/taverna_player/concerns/controllers/runs_controller.rb

Summary

Maintainability
A
2 hrs
Test Coverage
#------------------------------------------------------------------------------
# Copyright (c) 2013, 2014 The University of Manchester, UK.
#
# BSD Licenced. See LICENCE.rdoc for details.
#
# Taverna Player was developed in the BioVeL project, funded by the European
# Commission 7th Framework Programme (FP7), through grant agreement
# number 283359.
#
# Author: Robert Haines
#------------------------------------------------------------------------------

module TavernaPlayer
  module Concerns
    module Controllers
      module RunsController

        extend ActiveSupport::Concern

        include TavernaPlayer::Concerns::Callback
        include TavernaPlayer::Concerns::Utils

        included do
          respond_to :html, :json, :js

          before_filter :find_runs, :only => [ :index ]
          before_filter :find_run, :except => [ :index, :new, :create ]
          before_filter :find_workflow, :only => [ :new ]
          before_filter :find_port, :only => [ :download_input, :download_output, :input, :output ]
          before_filter :setup_new_run, :only => :new
          before_filter :set_run_user, :only => :create
          before_filter :filter_update_parameters, :only => :update
          before_filter :find_interaction, :only => [ :read_interaction, :write_interaction ]

          private

          def find_runs
            select = { :embedded => false }
            select[:workflow_id] = params[:workflow_id] if params[:workflow_id]
            @runs = Run.where(select).all
          end

          def find_run
            @run = Run.find(params[:id])
          end

          def find_workflow
            @workflow = TavernaPlayer.workflow_proxy.class_const.find(params[:workflow_id])
          end

          def find_port
            @port = RunPort.find_by_run_id_and_name(@run.id, params[:port])
          end

          def setup_new_run
            @run = Run.new(:workflow_id => @workflow.id)
            @run.embedded = true if params[:embedded] == "true"
          end

          def set_run_user
            return if params[:run][:embedded] == "true" || TavernaPlayer.user_proxy.nil?

            unless TavernaPlayer.current_user_callback.blank?
              user = callback(TavernaPlayer.current_user_callback)
              params[:run][:user_id] = user.id unless user.nil?
            end
          end

          def filter_update_parameters
            name = params[:run][:name]
            @update_parameters = { :name => name } unless name.blank?
          end

          def find_interaction
            @interaction = Interaction.find_by_run_id_and_serial(@run.id, params[:serial])
          end

          # Download an input or output port as an "attachment" (i.e. not
          # "inline").
          def download_port
            # If there is no such port then return a 404.
            raise ActionController::RoutingError.new('Not Found') if @port.nil?

            type = @port.depth == 0 ? @port.value_type : "application/zip"
            send_data @port.value, :type => type, :filename => @port.filename
          end

        end # included

        # GET /runs
        def index

        end

        # GET /runs/1
        def show
          if @run.running?
            @interaction = Interaction.find_by_run_id_and_replied(@run.id, false)
            unless @interaction.nil?
              unless @interaction.displayed
                @new_interaction = true
                @interaction.displayed = true
                @interaction.save
              end
            end
          end

          respond_with(@run) do |format|
            # Render show.{html|js}.erb unless the run is embedded.
            format.any(:html, :js) do
              render "taverna_player/runs/embedded/show", :layout => "taverna_player/embedded" if @run.embedded
            end
          end
        end

        # GET /runs/new
        def new
          respond_with(@run) do |format|
            # Render new.html.erb unless the run is embedded.
            format.html do
              render "taverna_player/runs/embedded/new", :layout => "taverna_player/embedded" if @run.embedded
            end
          end
        end

        # POST /runs
        def create
          @run = Run.new(params[:run])

          # Set workflow, just in case the create fails and needs to redirect
          # back to the form
          @workflow = @run.workflow

          if @run.save
            flash[:notice] = "Run was successfully created."
            respond_with(@run, :status => :created, :location => @run)
          else
            flash[:alert] = "Run was not successfully created."
            respond_with(@run)
          end
        end

        # PUT /runs/1
        def update
          @run.update_attributes(@update_parameters)

          respond_with(@run)
        end

        # DELETE /runs/1
        def destroy
          if @run.destroy
            flash[:notice] = "Run was deleted."
            respond_with(@run)
          else
            flash[:alert] = "Run must be cancelled before deletion."
            respond_with(@run, :nothing => true, :status => :forbidden) do |format|
              format.html { redirect_to :back }
            end
          end
        end

        # PUT /runs/1/cancel
        def cancel
          @run.cancel unless @run.complete?

          respond_with(@run, :action => :show) do |format|
            format.html do
              if @run.embedded?
                redirect_to view_context.new_embedded_run_path(@run)
              else
                redirect_to :back
              end
            end
          end
        end

        # GET /runs/1/download/log
        def download_log
          send_file @run.log.path, :type => "text/plain",
            :filename => "#{@run.name}-log.txt"
        end

        # GET /runs/1/download/results
        def download_results
          send_file @run.results.path, :type => "application/zip",
            :filename => "#{@run.name}-all-results.zip"
        end

        # GET /runs/1/download/input/:port
        def download_input
          download_port
        end

        # GET /runs/1/download/output/:port
        def download_output
          download_port
        end

        # GET /runs/1/input/*
        def input
          # If there is no such input port then return a 404.
          raise ActionController::RoutingError.new('Not Found') if @port.nil?

          send_data @port.value, :type => @port.value_type,
            :disposition => "inline"
        end

        # GET /runs/1/output/*
        def output
          # We need to parse out the path into a list of numbers here so we have
          # a list of indices into the file structure.
          path = []
          unless params[:path].nil?
            path = params[:path].split("/").map { |p| p.to_i }
          end

          # If there is no such output port or the path is the wrong depth then
          # return a 404.
          if @port.nil? || path.length != @port.depth
            raise ActionController::RoutingError.new('Not Found')
          end

          # Just need to mangle the MIME type when sending error messages.
          type = @port.value_is_error?(path) ? "text/plain" : @port.value_type(path)
          send_data @port.value(path), :type => type, :disposition => "inline"
        end

        # GET /runs/1/interaction/:int_id
        def read_interaction
          send_data @interaction.page, :type => "text/html",
            :disposition => "inline"
        end

        # POST /runs/1/interaction/:int_id
        def write_interaction
          @interaction.data = request.body.read
          @interaction.feed_reply = request.headers["X-Taverna-Interaction-Reply"]
          @interaction.save

          render :nothing => true, :status => 201
        end

      end
    end
  end
end