From 57ac34e9f44ac729bb647611f4646113862924cf Mon Sep 17 00:00:00 2001 From: zmagod Date: Wed, 3 Aug 2016 12:57:51 +0200 Subject: [PATCH] add samples to experiment page [fixes SCI-43] --- app/controllers/experiments_controller.rb | 5 +- app/datatables/sample_datatable.rb | 59 +++++++++++++++++++++-- app/models/project.rb | 13 +++++ 3 files changed, 72 insertions(+), 5 deletions(-) diff --git a/app/controllers/experiments_controller.rb b/app/controllers/experiments_controller.rb index 8bdbdab3d..c8394100a 100644 --- a/app/controllers/experiments_controller.rb +++ b/app/controllers/experiments_controller.rb @@ -83,8 +83,9 @@ class ExperimentsController < ApplicationController format.json do render json: ::SampleDatatable.new(view_context, @organization, - @experiment, - nil) + nil, + nil, + @experiment) end end end diff --git a/app/datatables/sample_datatable.rb b/app/datatables/sample_datatable.rb index c9f8b4f29..7c3afb35f 100644 --- a/app/datatables/sample_datatable.rb +++ b/app/datatables/sample_datatable.rb @@ -5,11 +5,16 @@ class SampleDatatable < AjaxDatatablesRails::Base ASSIGNED_SORT_COL = "assigned" - def initialize(view, organization, project = nil, my_module = nil) + def initialize(view, + organization, + project = nil, + my_module = nil, + experiment = nil) super(view) @organization = organization @project = project @my_module = my_module + @experiment = experiment end # Define sortable columns, so 1st column will be sorted by attribute in sortable_columns[0] @@ -119,6 +124,7 @@ class SampleDatatable < AjaxDatatablesRails::Base if @my_module @assigned_samples = @my_module.samples + samples = samples .joins( "LEFT OUTER JOIN sample_my_modules ON @@ -129,7 +135,20 @@ class SampleDatatable < AjaxDatatablesRails::Base .references(:sample_my_modules) elsif @project @assigned_samples = @project.assigned_samples - ids = @project.my_modules.select(:id) + ids = @project.my_modules_ids + + samples = samples + .joins( + "LEFT OUTER JOIN sample_my_modules ON + (samples.id = sample_my_modules.sample_id AND + (sample_my_modules.my_module_id IN (#{ids}) OR + sample_my_modules.id IS NULL))" + ) + .references(:sample_my_modules) + elsif @experiment + @assigned_samples = @experiment.assigned_samples + ids = @experiment.my_modules.select(:id) + samples = samples .joins( "LEFT OUTER JOIN sample_my_modules ON @@ -172,6 +191,39 @@ class SampleDatatable < AjaxDatatablesRails::Base # Depending on the sort, order nulls first or # nulls last on sample_my_modules association records.order("sample_my_modules.id NULLS #{sort_null_direction(params[:order].values[0])}") + elsif @experiment + # A very elegant solution to sort assigned samples at a experiment level + + # grabs the ids of samples which has a modules that belongs to this project + assigned = Sample + .joins('LEFT OUTER JOIN "sample_my_modules" ON "sample_my_modules"."sample_id" = "samples"."id"') + .joins('LEFT OUTER JOIN "my_modules" ON "my_modules"."id" = "sample_my_modules"."my_module_id"') + .where('"my_modules"."experiment_id" = ?', @experiment.id) + .where('"my_modules"."nr_of_assigned_samples" > 0') + .select('"samples"."id"') + .distinct + + # grabs the ids that are not the previous one but are still of the same organization + unassigned = Sample + .where('"samples"."organization_id" = ?', @organization.id) + .where('"samples"."id" NOT IN (?)', assigned) + .select('"samples"."id"') + .distinct + + # check the input param and merge the two arrays of ids + if params[:order].values[0]["dir"] == "asc" + ids = assigned + unassigned + elsif params[:order].values[0]["dir"] == "desc" + ids = unassigned + assigned + end + ids = ids.collect { |s| s.id } + + # order the records by input ids + order_by_index = ActiveRecord::Base.send( + :sanitize_sql_array, + ["position((',' || samples.id || ',') in ?)", + ids.join(',') + ','] ) + records.where(id: ids).order(order_by_index) elsif @project # A very elegant solution to sort assigned samples at a project level @@ -179,7 +231,8 @@ class SampleDatatable < AjaxDatatablesRails::Base assigned = Sample .joins('LEFT OUTER JOIN "sample_my_modules" ON "sample_my_modules"."sample_id" = "samples"."id"') .joins('LEFT OUTER JOIN "my_modules" ON "my_modules"."id" = "sample_my_modules"."my_module_id"') - .where('"my_modules"."project_id" = ?', @project.id) + .joins('LEFT OUTER JOIN "experiments" ON "experiments"."id" = "my_modules"."experiment_id"') + .where('"experiments"."project_id" = ?', @project.id) .where('"my_modules"."nr_of_assigned_samples" > 0') .select('"samples"."id"') .distinct diff --git a/app/models/project.rb b/app/models/project.rb index e4fd29c8c..0cd9e3d73 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -126,4 +126,17 @@ class Project < ActiveRecord::Base organization.log(final) end + def assigned_samples + Sample.joins(:my_modules).where(my_modules: { + id: my_modules_ids.split(',') + }) + end + + def my_modules_ids + ids = active_experiments.map do |exp| + exp.my_modules.pluck(:id) if exp.my_modules + end + ids.delete_if { |i| i.flatten.empty? } + ids.join(', ') + end end