diff --git a/app/assets/javascripts/sample_types.js b/app/assets/javascripts/sample_types.js index 2f832bed9f..1d933fd260 100644 --- a/app/assets/javascripts/sample_types.js +++ b/app/assets/javascripts/sample_types.js @@ -72,12 +72,10 @@ var SampleTypes = { attributeTypeChanged: function (e, resetSelection=true) { //check if it is a controlled vocab, and change the state of the controlled vocab selector if need be var use_cv = $j(this).find(':selected').data('use-cv'); - var is_ontology = $j(this).find(':selected').data('is-ontology'); var cv_element = $j(this).siblings('.controlled-vocab-block'); if (use_cv) { var cv_selection = cv_element.find('.controlled-vocab-selection'); cv_selection.find('option').show(); - cv_selection.find(`option[data-is-ontology="${!is_ontology}"]`).hide(); if (resetSelection) cv_selection.find('option:selected').prop("selected", false); cv_element.show(); } diff --git a/app/models/sample_attribute.rb b/app/models/sample_attribute.rb index e64e732a70..bf117fe9cc 100644 --- a/app/models/sample_attribute.rb +++ b/app/models/sample_attribute.rb @@ -22,6 +22,9 @@ class SampleAttribute < ApplicationRecord # sample type exists attr_reader :deferred_link_to_self + # whether this attribute is tied to a controlled vocab which is based on an ontology + delegate :ontology_based?, to: :sample_controlled_vocab, allow_nil: true + def title=(title) super store_accessor_name diff --git a/app/models/sample_attribute_type.rb b/app/models/sample_attribute_type.rb index d53e3191f0..f4cac9e336 100644 --- a/app/models/sample_attribute_type.rb +++ b/app/models/sample_attribute_type.rb @@ -5,6 +5,7 @@ class SampleAttributeType < ApplicationRecord has_many :sample_attributes, inverse_of: :sample_attribute_type has_many :extended_metadata_attributes, inverse_of: :sample_attribute_type + has_many :isa_template_attributes, class_name: 'TemplateAttribute', inverse_of: :sample_attribute_type before_save :set_defaults_attributes after_initialize :set_defaults_attributes @@ -108,10 +109,6 @@ def seek_data_file? base_type == Seek::Samples::BaseType::SEEK_DATA_FILE end - def ontology? - controlled_vocab? && title == 'Ontology' - end - def base_type_handler(additional_options = {}) Seek::Samples::AttributeTypeHandlers::AttributeTypeHandlerFactory.instance.for_base_type(base_type, additional_options) end diff --git a/app/views/sample_types/_sample_attribute_form.html.erb b/app/views/sample_types/_sample_attribute_form.html.erb index 4f01e78e1a..a641b022c3 100644 --- a/app/views/sample_types/_sample_attribute_form.html.erb +++ b/app/views/sample_types/_sample_attribute_form.html.erb @@ -55,13 +55,15 @@ <%= select_tag "#{field_name_prefix}[sample_attribute_type_id]", - options_for_select(displayed_sample_attribute_types.sort_by(&:title).sort_by { |t| t.default? ? 0 : 1 }.map { |t| [t.title, t.id,{'data-use-cv'=>t.controlled_vocab? || t.seek_cv_list?,'data-is-ontology'=>t.ontology?, 'data-is-seek-sample'=>t.seek_sample? || t.seek_sample_multi? }] }, attribute_type_id), + options_for_select(displayed_sample_attribute_types.sort_by(&:title).sort_by { |t| t.default? ? 0 : 1 }.map do |t| + [t.title, t.id,{'data-use-cv': t.controlled_vocab? || t.seek_cv_list?, 'data-is-seek-sample': t.seek_sample? || t.seek_sample_multi? }] + end , attribute_type_id), class: 'form-control sample-type-attribute-type', disabled: !allow_type_change, data: { attr: "type" } %>

<%= select_tag "#{field_name_prefix}[sample_controlled_vocab_id]", - options_for_select(SampleControlledVocab.all.map { |scv| [scv.title, scv.id, {'data-editable'=>scv.can_edit?, 'data-is-ontology'=>scv.custom_input?}] }, + options_for_select(SampleControlledVocab.all.map { |scv| [scv.title, scv.id, {'data-editable': scv.can_edit?}] }, sample_controlled_vocab_id), include_blank: true, class: 'form-control controlled-vocab-selection', diff --git a/app/views/templates/_template_attribute_form.html.erb b/app/views/templates/_template_attribute_form.html.erb index 0f9a37f8a5..e5a7d3b6ec 100644 --- a/app/views/templates/_template_attribute_form.html.erb +++ b/app/views/templates/_template_attribute_form.html.erb @@ -44,13 +44,15 @@ <%= select_tag "#{field_name_prefix}[sample_attribute_type_id]", - options_for_select(SampleAttributeType.all.sort_by(&:title).sort_by { |t| t.default? ? 0 : 1 }.map { |t| [t.title, t.id,{'data-is-cv'=>t.controlled_vocab?,'data-is-ontology'=>t.ontology?, 'data-is-seek-sample'=>t.seek_sample? || t.seek_sample_multi? }] }, attribute_type_id), + options_for_select(SampleAttributeType.all.sort_by(&:title).sort_by { |t| t.default? ? 0 : 1 }.map do |t| + [t.title, t.id,{'data-is-cv': t.controlled_vocab?,'data-is-seek-sample': t.seek_sample? || t.seek_sample_multi? }] + end, attribute_type_id), class: 'form-control sample-type-attribute-type', data: {attr: "type"} %>

<%= select_tag "#{field_name_prefix}[sample_controlled_vocab_id]", - options_for_select(SampleControlledVocab.all.map { |scv| [scv.title, scv.id, {'data-editable'=>scv.can_edit?, 'data-is-ontology'=>scv.custom_input?}] }, + options_for_select(SampleControlledVocab.all.map { |scv| [scv.title, scv.id, {'data-editable': scv.can_edit?}] }, sample_controlled_vocab_id),include_blank: true, class: 'form-control controlled-vocab-selection', data: {attr: "cv_id"} %> diff --git a/db/seeds/007_sample_attribute_types.seeds.rb b/db/seeds/007_sample_attribute_types.seeds.rb index c352b635c5..bf742410f2 100644 --- a/db/seeds/007_sample_attribute_types.seeds.rb +++ b/db/seeds/007_sample_attribute_types.seeds.rb @@ -61,12 +61,15 @@ seek_sample_type = SampleAttributeType.find_or_initialize_by(title:'Registered Sample') seek_sample_type.update(base_type: Seek::Samples::BaseType::SEEK_SAMPLE) -seek_sample_multi_type = SampleAttributeType.find_or_initialize_by(title:'Registered Sample (multiple)') +seek_sample_multi_type = SampleAttributeType.find_or_initialize_by(title:'Registered Sample List') seek_sample_multi_type.update(base_type: Seek::Samples::BaseType::SEEK_SAMPLE_MULTI) cv_type = SampleAttributeType.find_or_initialize_by(title:'Controlled Vocabulary') cv_type.update(base_type: Seek::Samples::BaseType::CV) +cv_list_type = SampleAttributeType.find_or_initialize_by(title:'Controlled Vocabulary List') +cv_list_type.update(base_type: Seek::Samples::BaseType::CV_LIST) + uri_type = SampleAttributeType.find_or_initialize_by(title:'URI') uri_type.update(base_type: Seek::Samples::BaseType::STRING, regexp: URI.regexp.to_s, placeholder: 'http://www.example.com/123', resolution:'\\0') @@ -79,12 +82,6 @@ data_file_type = SampleAttributeType.find_or_initialize_by(title: 'Registered Data file') data_file_type.update(base_type: Seek::Samples::BaseType::SEEK_DATA_FILE) -ontology_type = SampleAttributeType.find_or_initialize_by(title:'Ontology') -ontology_type.update(base_type: Seek::Samples::BaseType::CV) - -cv_list_type = SampleAttributeType.find_or_initialize_by(title:'Controlled Vocabulary List') -cv_list_type.update(base_type: Seek::Samples::BaseType::CV_LIST) - linked_extended_metadata_type = SampleAttributeType.find_or_initialize_by(title:'Linked Extended Metadata') linked_extended_metadata_type.update(base_type: Seek::Samples::BaseType::LINKED_EXTENDED_METADATA) diff --git a/lib/isa_exporter.rb b/lib/isa_exporter.rb index 8f550f57de..5971017cbe 100644 --- a/lib/isa_exporter.rb +++ b/lib/isa_exporter.rb @@ -173,7 +173,7 @@ def convert_ontologies sample_types = @investigation.studies.map(&:sample_types) + @investigation.assays.map(&:sample_type) sample_types.flatten.each do |sa| sa.sample_attributes.each do |atr| - source_ontologies << atr.sample_controlled_vocab.source_ontology if atr.sample_attribute_type.ontology? + source_ontologies << atr.sample_controlled_vocab.source_ontology if atr.ontology_based? end end source_ontologies.uniq.map { |s| { name: s, file: '', version: '', description: '' } } @@ -487,7 +487,7 @@ def extract_sample_ids(obj, type) end def get_ontology_details(sample_attribute, label, vocab_term) - is_ontology = sample_attribute.sample_attribute_type.ontology? + is_ontology = sample_attribute.ontology_based? iri = '' if is_ontology iri = diff --git a/lib/tasks/seek_upgrades.rake b/lib/tasks/seek_upgrades.rake index 8386449354..e1dc6476f5 100644 --- a/lib/tasks/seek_upgrades.rake +++ b/lib/tasks/seek_upgrades.rake @@ -12,6 +12,8 @@ namespace :seek do decouple_extracted_samples_projects link_sample_datafile_attributes strip_sample_attribute_pids + rename_registered_sample_multiple_attribute_type + remove_ontology_attribute_type ] # these are the tasks that are executes for each upgrade as standard, and rarely change @@ -48,8 +50,16 @@ namespace :seek do end end + task(rename_registered_sample_multiple_attribute_type: [:environment]) do + attr = SampleAttributeType.find_by(title:'Registered Sample (multiple)') + if attr + puts "..... Renaming sample attribute type 'Registered Sample (multiple)' to 'Registered Sample List'." + attr.update_column(:title, 'Registered Sample List') + end + end + task(strip_sample_attribute_pids: [:environment]) do - puts '... Stripping Sample Attribute PIds ...' + puts '..... Stripping Sample Attribute PIds ...' n = 0 SampleAttribute.where('pid is NOT NULL AND pid !=?','').each do |attribute| new_pid = attribute.pid.strip @@ -58,7 +68,33 @@ namespace :seek do n += 1 end end - puts "... Finished stripping #{n} Sample Attribute PIds." + puts "..... Finished stripping #{n} Sample Attribute PIds." + end + + task(remove_ontology_attribute_type: [:environment]) do + ontology_attr_type = SampleAttributeType.find_by(title:'Ontology') + cv_attr_type = SampleAttributeType.find_by(title:'Controlled Vocabulary') + if ontology_attr_type + puts '..... Removing the Ontology sample attribute type ...' + if cv_attr_type + if ontology_attr_type.sample_attributes.any? + puts "..... Moving #{ontology_attr_type.sample_attributes.count} sample attributes to Controlled Vocabulary" + ontology_attr_type.sample_attributes.each do |attr_type| + attr_type.update_column(:sample_attribute_type_id, cv_attr_type.id) + end + end + if ontology_attr_type.isa_template_attributes.any? + puts "..... Moving #{ontology_attr_type.isa_template_attributes.count} template attributes to Controlled Vocabulary" + ontology_attr_type.isa_template_attributes.each do |attr_type| + attr_type.update_column(:sample_attribute_type_id, cv_attr_type.id) + end + end + + ontology_attr_type.destroy + else + puts '..... Target Controlled Vocabulary attribute type not found' + end + end end task(decouple_extracted_samples_policies: [:environment]) do diff --git a/test/unit/sample_attribute_test.rb b/test/unit/sample_attribute_test.rb index 48085edd73..4270b2e7b8 100644 --- a/test/unit/sample_attribute_test.rb +++ b/test/unit/sample_attribute_test.rb @@ -330,6 +330,22 @@ class SampleAttributeTest < ActiveSupport::TestCase assert_equal '', attribute.short_pid end + test 'ontology_based?' do + attribute = FactoryBot.create(:sample_sample_attribute, sample_type: FactoryBot.create(:simple_sample_type)) + refute attribute.ontology_based? + + attribute = FactoryBot.create(:simple_string_sample_attribute, sample_type: FactoryBot.create(:simple_sample_type)) + refute attribute.ontology_based? + + attribute = FactoryBot.create(:apples_controlled_vocab_attribute, sample_type: FactoryBot.create(:simple_sample_type)) + refute attribute.sample_controlled_vocab.ontology_based? + refute attribute.ontology_based? + + attribute.sample_controlled_vocab = FactoryBot.create(:topics_controlled_vocab) + assert attribute.sample_controlled_vocab.ontology_based? + assert attribute.ontology_based? + end + private def valid_value?(attribute, value) diff --git a/test/unit/sample_attribute_type_test.rb b/test/unit/sample_attribute_type_test.rb index 1ecdc5e6d7..eee6d509ad 100644 --- a/test/unit/sample_attribute_type_test.rb +++ b/test/unit/sample_attribute_type_test.rb @@ -247,4 +247,22 @@ class SampleAttributeTypeTest < ActiveSupport::TestCase type = FactoryBot.create(:controlled_vocab_attribute_type) refute type.seek_data_file? end + + test 'isa_template_attributes' do + type = FactoryBot.create(:age_sample_attribute_type) + type2 = FactoryBot.create(:weight_sample_attribute_type) + + ta1 = FactoryBot.create(:template_attribute, sample_attribute_type: type) + ta2 = FactoryBot.create(:template_attribute, sample_attribute_type: type) + ta3 = FactoryBot.create(:template_attribute, sample_attribute_type: type) + ta4 = FactoryBot.create(:template_attribute, sample_attribute_type: type2) + + type.reload + template_attributes = type.isa_template_attributes + assert_equal 3, template_attributes.count + assert_includes template_attributes, ta1 + assert_includes template_attributes, ta2 + assert_includes template_attributes, ta3 + assert_not_includes template_attributes, ta4 + end end