SysMO-DB/seek

View on GitHub
app/controllers/sweeps_controller.rb

Summary

Maintainability
B
4 hrs
Test Coverage
class SweepsController < ApplicationController

  before_filter :workflows_enabled?

  skip_before_filter :restrict_guest_user, :only => :new
  before_filter :find_sweep, :except => [:create, :new, :index]
  before_filter :find_run, :only => :new
  before_filter :set_runlet_parameters, :only => :create
  before_filter :find_workflow_and_version, :only => :new
  before_filter :auth, :except => [ :index, :new, :create ]

  def show
    @runs = @sweep.runs.select { |r| r.can_view? }
  end

  def new
    @sweep = Sweep.new
  end

  def edit
    respond_to do |format|
      format.html
    end
  end

  def update
    @sweep.attributes = params[:sweep]

    if params[:sharing]
      @sweep.policy_or_default
      @sweep.policy.set_attributes_with_sharing params[:sharing], @sweep.projects
    end

    if @sweep.save
      respond_to do |format|
        format.html { redirect_to sweep_path(@sweep) }
      end
    else
      respond_to do |format|
        format.html { render edit_sweep_path(@sweep) }
      end
    end
  end

  def create
    @sweep = Sweep.new(params[:sweep])
    @workflow = @sweep.workflow
    @workflow_version = @workflow.find_version(@sweep.workflow_version)

    raise if @workflow.nil?
    # Manually add projects of current user, as they aren't prompted for this information in the form
    @sweep.projects = current_user.person.projects
    @sweep.policy.set_attributes_with_sharing params[:sharing], @sweep.projects
    respond_to do |format|
      if @sweep.save
        format.html { redirect_to sweep_path(@sweep) }
      else
        format.html { render :action => "new" }
      end
    end
  end

  def cancel
    @sweep.cancel
    respond_to do |format|
      format.html { redirect_to taverna_player.runs_path }
    end
  end

  def destroy
    @sweep.destroy
    respond_to do |format|
      format.html { redirect_to params[:redirect_to].blank? ? taverna_player.runs_path : params[:redirect_to]}
    end
  end

  def runs
    @sweep = Sweep.find(params[:id], :include => {:runs => :workflow})
    @runs = @sweep.runs.select { |r| r.can_view? }
    respond_to do |format|
      format.js { render "taverna_player/runs/index" }
    end
  end

  # Display the result value for a given output port of a given run.
  def view_result
    respond_to do |format|
      format.js  { render 'view_result.js.erb' }
    end
  end

  # Zip/assemble results for a given output port over selected sweep's runs,
  # results for a run (for all output ports), or all results for all output ports
  # and all runs.
  def download_results
    @sweep = Sweep.find(params[:id], :include => { :runs => :outputs })

    if params[:download].blank?
      respond_to do |format|
        flash[:error] = "You must select at least one output to download"
        format.html { redirect_to :back }
      end
    else
      outputs = []
      params[:download].each do |run_id, output_names|
        outputs = outputs + @sweep.runs.detect {|r| r.id == run_id.to_i}.outputs.select {|o| output_names.include?(o.name)}
      end

      path = @sweep.build_zip(outputs)

      respond_to do |format|
        format.html {send_file path, :type => "application/zip",
          :filename => path.split('/').last }
      end
    end
  end

  private

  def find_run
    if !params[:run_id].blank? # New sweep based on a previous special_run
      @run = TavernaPlayer::Run.find(params[:run_id], :include => :inputs)
    else # New sweep from scratch
      @run = nil
    end
  end

  def find_workflow_and_version
    if !@run.blank?
      @workflow = @run.workflow
      @workflow_version = @run.executed_workflow
    else
      @workflow = Workflow.find(params[:workflow_id])
      @workflow_version = params[:version].blank? ? @workflow.latest_version : @workflow.find_version(params[:version])
    end
  end

  def set_runlet_parameters

    shared_input_values_for_all_runs = params[:sweep].delete(:shared_input_values_for_all_runs)
    params[:sweep][:runs_attributes].each_with_index do |(run_id, run_attributes), iteration_index|
      run_attributes[:workflow_id] = params[:sweep][:workflow_id]
      run_attributes[:workflow_version] = params[:sweep][:workflow_version]

      # Set parent ID to replay interactions
      run_attributes[:parent_id] = params[:run_id].to_i unless params[:run_id].blank?
      run_attributes[:project_ids] = current_user.person.projects.map { |p| p.id }

      # Copy shared inputs from "parent" run
      if !shared_input_values_for_all_runs.blank?
        base_index = run_attributes[:inputs_attributes].keys.map { |k| k.to_i }.max + 1
        if shared_input_values_for_all_runs[:inputs_attributes]
          shared_input_values_for_all_runs[:inputs_attributes].each do |input_id, input_attributes|
            run_attributes[:inputs_attributes][(base_index + input_id.to_i).to_s] = input_attributes
          end
        end
      end

      # Set the runlet names based on their input data, or just number them
      unless params[:name_input].blank?
        i = run_attributes[:inputs_attributes].values.detect {|v| v[:name] == params[:name_input]}
        if i[:file]
          identifier = "#{i[:file].original_filename}"
        elsif !i[:value].blank?
          identifier = "#{i[:value][0...32]}"
          identifier << '...' if i[:value].length > 32
        end
      end
      identifier ||= "(#{iteration_index + 1})"
      run_attributes[:name] = "#{params[:sweep][:name]} - #{identifier}"

      # Set the project for each runlet
      run_attributes[:project_ids] = current_user.person.projects.map { |p| p.id }
    end
  end

  def auth
    action = translate_action(action_name)
    unless is_auth?(@sweep, action)
      if User.current_user.nil?
        flash[:error] = "You are not authorized to #{action} this Sweep, you may need to login first."
      else
        flash[:error] = "You are not authorized to #{action} this Sweep."
      end
      respond_to do |format|
        format.html do
          case action
            when 'manage','edit','download','delete'
              redirect_to @sweep
            else
              redirect_to taverna_player.runs_path
          end
        end
      end
    end
  end

  def find_sweep
    @sweep = Sweep.find(params[:id], :include => :runs)
  end

end