diff --git a/app/controllers/templates_controller.rb b/app/controllers/templates_controller.rb
index 821b8082b6..2b7d204b9b 100644
--- a/app/controllers/templates_controller.rb
+++ b/app/controllers/templates_controller.rb
@@ -107,7 +107,7 @@ def populate_template
begin
running!
- PopulateTemplatesJob.new.queue_job
+ PopulateTemplatesJob.perform_later(@current_user)
rescue StandardError
done!
end
diff --git a/app/jobs/populate_templates_job.rb b/app/jobs/populate_templates_job.rb
index e9b8afc086..aac040d90c 100644
--- a/app/jobs/populate_templates_job.rb
+++ b/app/jobs/populate_templates_job.rb
@@ -2,9 +2,9 @@
class PopulateTemplatesJob < ApplicationJob
queue_with_priority 1
queue_as QueueNames::TEMPLATES
- def perform
+ def perform(user)
return unless Seek::Config.isa_json_compliance_enabled
- Seek::IsaTemplates::TemplateExtractor.extract_templates
+ Seek::IsaTemplates::TemplateExtractor.extract_templates(user)
end
end
diff --git a/lib/seek/isa_templates/template_attributes_schema.json b/lib/seek/isa_templates/template_attributes_schema.json
index ceed37ba58..334f831d7c 100644
--- a/lib/seek/isa_templates/template_attributes_schema.json
+++ b/lib/seek/isa_templates/template_attributes_schema.json
@@ -1,112 +1,140 @@
{
- "$schema": "http://json-schema.org/draft-04/schema",
- "title": "ISA tempalte attribute schema",
- "description": "JSON-schema representing an ISA template attribute in DataHub",
- "type": "object",
- "properties": {
- "iri": {
- "anyOf": [
- {
- "type": "string",
- "format": "uri"
- },
- {
- "type": "null"
- }
- ]
- },
- "name": { "type": "string" },
- "description": { "type": "string" },
- "required": {
- "anyOf": [
- {
- "type": "boolean"
- },
- {
- "type": "null"
- }
- ]
- },
- "ontology": {
- "anyOf": [
- {
- "type": "object",
- "properties": {
- "name": { "type": "string" },
- "version": {
- "anyOf": [{ "type": "string" }, { "type": "number" }]
- },
- "description": { "type": "string" },
- "rootTermURI": { "type": "string", "format": "uri" }
- }
- },
- {
- "type": "null"
- }
- ]
- },
- "dataType": {
- "type": "string",
- "enum": [
- "Date time",
- "Date",
- "Real number",
- "Integer",
- "Web link",
- "Email address",
- "Text",
- "String",
- "Boolean",
- "Registered Sample",
- "Registered Sample List",
- "Controlled Vocabulary",
- "URI",
- "Registered Data file",
- "ENA custom date"
- ]
- },
- "CVList": {
- "anyOf": [
- {
- "type": "array"
- },
- {
- "type": "null"
- }
- ]
- },
- "isaTag": {
- "anyOf": [
- {
- "type": "string",
- "enum": [
- "source",
- "sample",
- "protocol",
- "source_characteristic",
- "sample_characteristic",
- "other_material",
- "other_material_characteristic",
- "data_file",
- "data_file_comment",
- "parameter_value"
- ]
- },
- {
- "type": "null"
- }
- ]
- },
- "title": {
- "anyOf": [
- {
- "type": "boolean"
- },
- {
- "type": "null"
- }
- ]
- }
- },
- "additionalProperties": false
+ "$schema": "http://json-schema.org/draft-04/schema",
+ "title": "ISA tempalte attribute schema",
+ "description": "JSON-schema representing an ISA template attribute in DataHub",
+ "type": "object",
+ "properties": {
+ "iri": {
+ "anyOf": [
+ {
+ "type": "string",
+ "format": "uri"
+ },
+ {
+ "type": "null"
+ }
+ ]
+ },
+ "name": {
+ "type": "string"
+ },
+ "description": {
+ "type": "string"
+ },
+ "required": {
+ "anyOf": [
+ {
+ "type": "boolean"
+ },
+ {
+ "type": "null"
+ }
+ ]
+ },
+ "ontology": {
+ "anyOf": [
+ {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "version": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "number"
+ }
+ ]
+ },
+ "description": {
+ "type": "string"
+ },
+ "rootTermURI": {
+ "type": "string",
+ "format": "uri"
+ }
+ }
+ },
+ {
+ "type": "null"
+ }
+ ]
+ },
+ "dataType": {
+ "type": "string",
+ "enum": [
+ "Date time",
+ "Date",
+ "Real number",
+ "Integer",
+ "Web link",
+ "Email address",
+ "Text",
+ "String",
+ "Boolean",
+ "Registered Sample",
+ "Registered Sample List",
+ "Controlled Vocabulary",
+ "URI",
+ "Registered Data file",
+ "ENA custom date"
+ ]
+ },
+ "allowCVFreeText": {
+ "anyOf": [
+ {
+ "type": "boolean"
+ },
+ {
+ "type": "null"
+ }
+ ]
+ },
+ "CVList": {
+ "anyOf": [
+ {
+ "type": "array"
+ },
+ {
+ "type": "null"
+ }
+ ]
+ },
+ "isaTag": {
+ "anyOf": [
+ {
+ "type": "string",
+ "enum": [
+ "source",
+ "sample",
+ "protocol",
+ "source_characteristic",
+ "sample_characteristic",
+ "other_material",
+ "other_material_characteristic",
+ "data_file",
+ "data_file_comment",
+ "parameter_value"
+ ]
+ },
+ {
+ "type": "null"
+ }
+ ]
+ },
+ "title": {
+ "anyOf": [
+ {
+ "type": "boolean"
+ },
+ {
+ "type": "null"
+ }
+ ]
+ }
+ },
+ "additionalProperties": false
}
diff --git a/lib/seek/isa_templates/template_attributes_schema_test.json b/lib/seek/isa_templates/template_attributes_schema_test.json
index 23528693ba..b2d16f4092 100644
--- a/lib/seek/isa_templates/template_attributes_schema_test.json
+++ b/lib/seek/isa_templates/template_attributes_schema_test.json
@@ -1,99 +1,152 @@
{
- "$schema": "http://json-schema.org/draft-04/schema",
- "title": "ISA tempalte attribute schema",
- "description": "JSON-schema representing an ISA template attribute in DataHub",
- "type": "object",
- "properties": {
- "iri": {
- "anyOf": [
- {
- "type": "string",
- "format": "uri"
- },
- {
- "type": "null"
- }
- ]
- },
- "name": { "type": "string" },
- "description": { "type": "string" },
- "required": {
- "anyOf": [
- {
- "type": "boolean"
- },
- {
- "type": "null"
- }
- ]
- },
- "ontology": {
- "anyOf": [
- {
- "type": "object",
- "properties": {
- "name": { "type": "string" },
- "version": {
- "anyOf": [{ "type": "string" }, { "type": "number" }]
- },
- "description": { "type": "string" },
- "rootTermURI": { "type": "string", "format": "uri" }
- }
- },
- {
- "type": "null"
- }
- ]
- },
- "dataType": {
- "type": "string",
- "enum": [
- "String attribute type 1",
- "Sample multi attribute type 1"
- ]
- },
- "CVList": {
- "anyOf": [
- {
- "type": "array"
- },
- {
- "type": "null"
- }
- ]
- },
- "isaTag": {
- "anyOf": [
- {
- "type": "string",
- "enum": [
- "source",
- "sample",
- "protocol",
- "source_characteristic",
- "sample_characteristic",
- "other_material",
- "other_material_characteristic",
- "data_file",
- "data_file_comment",
- "parameter_value"
- ]
- },
- {
- "type": "null"
- }
- ]
- },
- "title": {
- "anyOf": [
- {
- "type": "boolean"
- },
- {
- "type": "null"
- }
- ]
- }
- },
- "additionalProperties": false
+ "$schema": "http://json-schema.org/draft-04/schema",
+ "title": "ISA template attribute schema",
+ "description": "JSON-schema representing an ISA template attribute in DataHub",
+ "type": "object",
+ "properties": {
+ "iri": {
+ "anyOf": [
+ {
+ "type": "string",
+ "format": "uri"
+ },
+ {
+ "type": "null"
+ }
+ ]
+ },
+ "name": {
+ "type": "string"
+ },
+ "description": {
+ "type": "string"
+ },
+ "required": {
+ "anyOf": [
+ {
+ "type": "boolean"
+ },
+ {
+ "type": "null"
+ }
+ ]
+ },
+ "ontology": {
+ "anyOf": [
+ {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "version": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "number"
+ }
+ ]
+ },
+ "description": {
+ "type": "string"
+ },
+ "rootTermURI": {
+ "type": "string",
+ "format": "uri"
+ }
+ }
+ },
+ {
+ "type": "null"
+ }
+ ]
+ },
+ "dataType": {
+ "type": "string",
+ "enum": [
+ "Date time",
+ "Date",
+ "Real number",
+ "Integer",
+ "Web link",
+ "Email address",
+ "Text",
+ "String",
+ "ChEBI",
+ "ECN",
+ "MetaNetX chemical",
+ "MetaNetX reaction",
+ "MetaNetX compartment",
+ "InChI",
+ "ENA custom date",
+ "Boolean",
+ "Registered Strain",
+ "Registered Sample",
+ "Registered Sample List",
+ "Controlled Vocabulary",
+ "Controlled Vocabulary List",
+ "URI",
+ "DOI",
+ "NCBI ID",
+ "Registered Data file",
+ "Linked Extended Metadata",
+ "Linked Extended Metadata (multiple)"
+ ]
+ },
+ "allowCVFreeText": {
+ "anyOf": [
+ {
+ "type": "boolean"
+ },
+ {
+ "type": "null"
+ }
+ ]
+ },
+ "CVList": {
+ "anyOf": [
+ {
+ "type": "array"
+ },
+ {
+ "type": "null"
+ }
+ ]
+ },
+ "isaTag": {
+ "anyOf": [
+ {
+ "type": "string",
+ "enum": [
+ "source",
+ "sample",
+ "protocol",
+ "source_characteristic",
+ "sample_characteristic",
+ "other_material",
+ "other_material_characteristic",
+ "data_file",
+ "data_file_comment",
+ "parameter_value"
+ ]
+ },
+ {
+ "type": "null"
+ }
+ ]
+ },
+ "title": {
+ "anyOf": [
+ {
+ "type": "boolean"
+ },
+ {
+ "type": "null"
+ }
+ ]
+ }
+ },
+ "additionalProperties": false
}
diff --git a/lib/seek/isa_templates/template_extractor.rb b/lib/seek/isa_templates/template_extractor.rb
index 4f11d633db..6e0c80c0bf 100644
--- a/lib/seek/isa_templates/template_extractor.rb
+++ b/lib/seek/isa_templates/template_extractor.rb
@@ -3,13 +3,12 @@
module Seek
module IsaTemplates
module TemplateExtractor
- def self.extract_templates
+ def self.extract_templates(user)
FileUtils.touch(resultfile)
result = StringIO.new
seed_isa_tags
- disable_authorization_checks do
- client = Ebi::OlsClient.new
+ User.with_current_user(user) do
project = Project.find_or_create_by(title: 'Default Project')
directory = Seek::Config.append_filestore_path('source_types')
@directory_files = Dir.exist?(directory) ? Dir.glob("#{directory}/*.json") : []
@@ -38,54 +37,16 @@ def self.extract_templates
current_template_attributes = []
item['data'].each_with_index do |attribute, j|
- is_ontology = attribute['ontology'].present?
- is_cv = attribute['CVList'].present?
- if is_ontology || is_cv
- scv =
- SampleControlledVocab.new(
- {
- title: attribute['name'],
- source_ontology: is_ontology ? attribute['ontology']['name'] : nil,
- ols_root_term_uris: is_ontology ? attribute['ontology']['rootTermURI'] : nil
- }
- )
- end
-
- if is_ontology
- if attribute['ontology']['rootTermURI'].present?
- begin
- terms = client.all_descendants(attribute['ontology']['name'],
- attribute['ontology']['rootTermURI'])
- rescue StandardError => e
- scv.save(validate: false)
- next
- end
- terms.each_with_index do |term, i|
- puts "#{j}) #{i + 1} FROM #{terms.length}"
- if i.zero?
- # Skip the parent name
- des = term[:description]
- scv[:description] = des.is_a?(Array) ? des[0] : des
- elsif term[:label].present? && term[:iri].present?
- cvt =
- SampleControlledVocabTerm.new(
- { label: term[:label], iri: term[:iri], parent_iri: term[:parent_iri] }
- )
- scv.sample_controlled_vocab_terms << cvt
- end
- end
- end
- elsif is_cv
- # the CV terms
- if attribute['CVList'].present?
- attribute['CVList'].each do |term|
- cvt = SampleControlledVocabTerm.new({ label: term })
- scv.sample_controlled_vocab_terms << cvt
- end
- end
+ is_cv = attribute['dataType'].include? 'Controlled Vocabulary'
+ allow_cv_free_text = false
+ if is_cv
+ is_ontology = attribute['ontology'].present?
+ cv_exists = !SampleControlledVocab.find_by(title: attribute['name']).nil?
+ allow_cv_free_text = attribute['allowCVFreeText'].present? ? attribute['allowCVFreeText'] : false
+
+ scv = cv_exists ? SampleControlledVocab.find_by(title: attribute['name']) : initialize_sample_controlled_vocab(template_details, attribute, is_ontology)
end
-
- p scv.errors if (is_ontology || is_cv) && !scv.save(validate: false)
+ p scv.errors if is_cv && !scv.save(validate: false)
ta = TemplateAttribute.new(is_title: (attribute['title'] || 0),
isa_tag_id: get_isa_tag_id(attribute['isaTag']),
@@ -95,12 +56,13 @@ def self.extract_templates
sample_controlled_vocab_id: scv&.id,
pid: attribute['pid'],
sample_attribute_type_id: get_sample_attribute_type(attribute['dataType']),
- allow_cv_free_text: attribute['ontology'].present?,
+ allow_cv_free_text: allow_cv_free_text,
title: attribute['name'])
current_template_attributes.append ta
end
template.template_attributes << current_template_attributes
+ template.contributor = nil
template.save! unless @errors.present?
end
@@ -118,6 +80,51 @@ def self.extract_templates
FileUtils.rm_f(@directory_files) unless @directory_files.blank?
end
+ def self.initialize_sample_controlled_vocab(template_details, attribute, is_ontology = false)
+ scv = SampleControlledVocab.new(
+ {
+ title: attribute['name'],
+ source_ontology: is_ontology ? attribute['ontology']['name'] : nil,
+ ols_root_term_uris: is_ontology ? attribute['ontology']['rootTermURI'] : nil
+ }
+ )
+
+ if is_ontology
+ client = Ebi::OlsClient.new
+ if attribute['ontology']['rootTermURI'].present?
+ begin
+ terms = client.all_descendants(attribute['ontology']['name'],
+ attribute['ontology']['rootTermURI'])
+ rescue StandardError => e
+ add_log(template_details, "Failed to fetch terms from OLS for attribute '#{attribute['name']}'. Please add terms manually!")
+ Rails.logger.debug("Failed to fetch terms from OLS for attribute '#{attribute['name']}'. Error: #{e}")
+ terms = []
+ end
+ terms.each_with_index do |term, i|
+ puts "#{j}) #{i + 1} FROM #{terms.length}"
+ if i.zero?
+ # Skip the parent name
+ des = term[:description]
+ scv[:description] = des.is_a?(Array) ? des[0] : des
+ elsif term[:label].present? && term[:iri].present?
+ cvt =
+ SampleControlledVocabTerm.new(
+ { label: term[:label], iri: term[:iri], parent_iri: term[:parent_iri] }
+ )
+ scv.sample_controlled_vocab_terms << cvt
+ end
+ end
+ end
+ else
+ # the CV terms
+ attribute['CVList'].each do |term|
+ cvt = SampleControlledVocabTerm.new({ label: term })
+ scv.sample_controlled_vocab_terms << cvt
+ end
+ end
+ scv
+ end
+
def self.init_template(metadata)
{
title: metadata['name'],
@@ -169,7 +176,7 @@ def self.valid_isa_json?(json)
end
def self.get_sample_attribute_type(title)
- sa = SampleAttributeType.find_by(title:)
+ sa = SampleAttributeType.find_by(title: title)
@errors.append "
Could not find a Sample Attribute Type named '#{title}'" if sa.nil?
return if sa.nil?
@@ -180,10 +187,10 @@ def self.get_sample_attribute_type(title)
def self.get_isa_tag_id(title)
return nil if title.blank?
- it = IsaTag.find_by(title:)
+ it = IsaTag.find_by(title: title)
@errors.append "Could not find an ISA Tag named '#{title}'" if it.nil?
- it.id
+ it&.id
end
def self.seed_isa_tags
diff --git a/test/fixtures/files/upload_json_sample_type_template/test_apple_cv_template.json b/test/fixtures/files/upload_json_sample_type_template/test_apple_cv_template.json
new file mode 100644
index 0000000000..4eaef0dd67
--- /dev/null
+++ b/test/fixtures/files/upload_json_sample_type_template/test_apple_cv_template.json
@@ -0,0 +1,102 @@
+{
+ "data": [
+ {
+ "metadata": {
+ "name": "Test Apple CV Template",
+ "group": "SEEK Test",
+ "group_order": 1,
+ "temporary_name": "1_test_apple_cv_template",
+ "version": "1.0.0",
+ "isa_config": null,
+ "isa_measurement_type": null,
+ "isa_technology_type": null,
+ "isa_protocol_type": null,
+ "repo_schema_id": null,
+ "organism": "any",
+ "level": "study source"
+ },
+ "data": [
+ {
+ "iri": null,
+ "name": "Source Name",
+ "description": "Sources are considered as the starting biological material used in a study.",
+ "dataType": "String",
+ "title": true,
+ "required": true,
+ "isaTag": "source"
+ },
+ {
+ "iri": null,
+ "name": "Source Characteristic 1",
+ "description": "A characteristic of the source",
+ "dataType": "String",
+ "required": true,
+ "ontology": null,
+ "allowCVFreeText": null,
+ "CVList": null,
+ "isaTag": "source_characteristic"
+ },
+ {
+ "iri": null,
+ "name": "apples controlled vocab for template",
+ "description": "",
+ "dataType": "Controlled Vocabulary",
+ "required": false,
+ "ontology": null,
+ "allowCVFreeText": true,
+ "CVList": [
+ "Granny Smith",
+ "Golden Delicious",
+ "Bramley",
+ "Cox's Orange Pippin"
+ ],
+ "isaTag": "source_characteristic"
+ },
+ {
+ "iri": null,
+ "name": "physics ontology",
+ "description": "",
+ "dataType": "Controlled Vocabulary List",
+ "required": false,
+ "ontology": {
+ "name": "edam",
+ "version": "",
+ "description": "The study of matter, space and time, and related concepts such as energy and force.",
+ "rootTermURI": "http://edamontology.org/topic_3318"
+ },
+ "allowCVFreeText": false,
+ "CVList": null,
+ "isaTag": "source_characteristic"
+ },
+ {
+ "iri": null,
+ "name": "New CV List",
+ "description": "",
+ "dataType": "Controlled Vocabulary List",
+ "required": false,
+ "ontology": null,
+ "CVList": [
+ "term 1",
+ "term 2"
+ ],
+ "isaTag": "source_characteristic"
+ },
+ {
+ "iri": null,
+ "name": "New ontology List",
+ "description": "",
+ "dataType": "Controlled Vocabulary List",
+ "required": false,
+ "ontology": {
+ "name": "FBbi",
+ "version": "",
+ "description": "Imaging method",
+ "rootTermURI": "http://purl.obolibrary.org/obo/FBbi_00000222"
+ },
+ "CVList": null,
+ "isaTag": "source_characteristic"
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/test/fixtures/files/upload_json_sample_type_template/test_templates.json b/test/fixtures/files/upload_json_sample_type_template/test_templates.json
index ce4e2f20cc..0643aee1af 100644
--- a/test/fixtures/files/upload_json_sample_type_template/test_templates.json
+++ b/test/fixtures/files/upload_json_sample_type_template/test_templates.json
@@ -20,7 +20,7 @@
"iri": null,
"name": "Source Name",
"description": "Sources are considered as the starting biological material used in a study.",
- "dataType": "String attribute type 1",
+ "dataType": "String",
"title": true,
"required": true,
"isaTag": "source"
@@ -29,7 +29,7 @@
"iri": null,
"name": "Source Characteristic 1",
"description": "A characteristic of the source.",
- "dataType": "String attribute type 1",
+ "dataType": "String",
"required": true,
"ontology": null,
"CVList": null,
@@ -57,7 +57,7 @@
"iri": null,
"name": "Input",
"description": "Registered Samples in the platform used as input for this protocol.",
- "dataType": "Sample multi attribute type 1",
+ "dataType": "Registered Sample List",
"required": true,
"isaTag": null
},
@@ -65,7 +65,7 @@
"iri": null,
"name": "Name of a protocol with samples as outputs",
"description": "Type of experimental step that generates samples as outputs from the study sources.",
- "dataType": "String attribute type 1",
+ "dataType": "String",
"required": true,
"ontology": null,
"CVList": null,
@@ -75,7 +75,7 @@
"iri": null,
"name": "Name of protocol parameter 1",
"description": "A parameter for the protocol.",
- "dataType": "String attribute type 1",
+ "dataType": "String",
"required": true,
"ontology": null,
"CVList": null,
@@ -85,7 +85,7 @@
"iri": null,
"name": "Sample Name",
"description": "Samples are considered as biological material sampled from sources and used in the study.",
- "dataType": "String attribute type 1",
+ "dataType": "String",
"title": true,
"required": true,
"isaTag": "sample"
@@ -94,7 +94,7 @@
"iri": null,
"name": "Sample Characteristic 1",
"description": "A characteristic of the sample.",
- "dataType": "String attribute type 1",
+ "dataType": "String",
"required": true,
"ontology": null,
"CVList": null,
@@ -122,7 +122,7 @@
"iri": null,
"name": "Input",
"description": "Registered Samples in the platform used as input for this protocol.",
- "dataType": "Sample multi attribute type 1",
+ "dataType": "Registered Sample List",
"required": true,
"isaTag": null
},
@@ -130,7 +130,7 @@
"iri": null,
"name": "Name of a protocol with material output",
"description": "Type of assay or experimental step performed that generates a material output.",
- "dataType": "String attribute type 1",
+ "dataType": "String",
"required": true,
"ontology": null,
"CVList": null,
@@ -140,7 +140,7 @@
"iri": null,
"name": "Name of protocol parameter 1",
"description": "A parameter for the protocol.",
- "dataType": "String attribute type 1",
+ "dataType": "String",
"required": true,
"ontology": null,
"CVList": null,
@@ -150,7 +150,7 @@
"iri": null,
"name": "Output material Name",
"description": "Name of the major material output resulting from the application of the protocol.",
- "dataType": "String attribute type 1",
+ "dataType": "String",
"title": true,
"required": true,
"isaTag": "other_material"
@@ -159,7 +159,7 @@
"iri": null,
"name": "Output material characteristic 1",
"description": "Characteristic 1 of the output material.",
- "dataType": "String attribute type 1",
+ "dataType": "String",
"required": true,
"ontology": null,
"CVList": null,
@@ -187,7 +187,7 @@
"iri": null,
"name": "Input",
"description": "Registered Samples in the platform used as input for this protocol.",
- "dataType": "Sample multi attribute type 1",
+ "dataType": "Registered Sample List",
"required": true,
"isaTag": null
},
@@ -195,7 +195,7 @@
"iri": null,
"name": "Name of a protocol with data file output",
"description": "Type of assay or experimental step performed that generates a data file output.",
- "dataType": "String attribute type 1",
+ "dataType": "String",
"required": true,
"ontology": null,
"CVList": null,
@@ -205,7 +205,7 @@
"iri": null,
"name": "Name of protocol parameter 1",
"description": "A parameter for the protocol.",
- "dataType": "String attribute type 1",
+ "dataType": "String",
"required": true,
"ontology": null,
"CVList": null,
@@ -215,7 +215,7 @@
"iri": null,
"name": "Data file Name",
"description": "Name of the major data file output resulting from the application of the protocol.",
- "dataType": "String attribute type 1",
+ "dataType": "String",
"title": true,
"required": true,
"isaTag": "data_file"
@@ -224,7 +224,7 @@
"iri": null,
"name": "Data file characteristic 1",
"description": "Characteristic 1 of the data file output.",
- "dataType": "String attribute type 1",
+ "dataType": "String",
"required": true,
"ontology": null,
"CVList": null,
diff --git a/test/functional/templates_controller_test.rb b/test/functional/templates_controller_test.rb
index 566f16496f..9673aeab8d 100644
--- a/test/functional/templates_controller_test.rb
+++ b/test/functional/templates_controller_test.rb
@@ -14,17 +14,18 @@ class TemplatesControllerTest < ActionController::TestCase
FactoryBot.create(:person) # to prevent person being first person and therefore admin
@person = FactoryBot.create(:project_administrator)
+ @admin = FactoryBot.create(:admin)
@project = @person.projects.first
@project_ids = [@project.id]
refute_nil @project
login_as(@person)
@template = FactoryBot.create(:min_template, project_ids: @project_ids, contributor: @person)
- @string_type = FactoryBot.create(:string_sample_attribute_type)
- @int_type = FactoryBot.create(:integer_sample_attribute_type)
- @registered_sample_attribute_type = FactoryBot.create(:sample_sample_attribute_type)
- @registered_sample_multi_attribute_type = FactoryBot.create(:sample_multi_sample_attribute_type)
- @controlled_vocab_type = FactoryBot.create(:controlled_vocab_attribute_type)
- @controlled_vocab_list_type = FactoryBot.create(:cv_list_attribute_type)
+ @string_type = SampleAttributeType.find_by(title: "String").nil? ? FactoryBot.create(:string_sample_attribute_type, title: "string") : SampleAttributeType.find_by(title: "String")
+ @int_type = SampleAttributeType.find_by(title: "Integer").nil? ? FactoryBot.create(:integer_sample_attribute_type) : SampleAttributeType.find_by(title: "Integer")
+ @registered_sample_attribute_type = SampleAttributeType.find_by(title: "Registered Sample").nil? ? FactoryBot.create(:sample_sample_attribute_type) : SampleAttributeType.find_by(title: "Registered Sample")
+ @registered_sample_multi_attribute_type = SampleAttributeType.find_by(title: "Registered Sample List").nil? ? FactoryBot.create(:sample_multi_sample_attribute_type) : SampleAttributeType.find_by(title: "Registered Sample List")
+ @controlled_vocab_type = SampleAttributeType.find_by(title: "Controlled Vocabulary").nil? ? FactoryBot.create(:controlled_vocab_attribute_type) : SampleAttributeType.find_by(title: "Controlled Vocabulary")
+ @controlled_vocab_list_type = SampleAttributeType.find_by(title: "Controlled Vocabulary List").nil? ? FactoryBot.create(:cv_list_attribute_type) : SampleAttributeType.find_by(title: "Controlled Vocabulary List")
@default_isa_tag = FactoryBot.create(:default_isa_tag)
end
@@ -650,6 +651,72 @@ class TemplatesControllerTest < ActionController::TestCase
assert_select 'script#project-selector-possibilities-json', text: /#{options}/, count: 1
end
+ test 'should reuse existing controlled vocabularies' do
+ apples_cv = FactoryBot.create(:apples_sample_controlled_vocab, title: "apples controlled vocab for template", )
+ physics_ontology = FactoryBot.create(:sample_controlled_vocab, title: "physics ontology", source_ontology: "edam", ols_root_term_uris: "http://edamontology.org/topic_3318")
+ assert_equal SampleControlledVocab.count, 2
+
+ login_as(@admin)
+ ####################################################################################################################
+ # This file contains the JSON definition for 1 template with 6 template attributes:
+ # 1. Source Name (Sting) => New
+ # 2. Source Characteristic 1 (String) => New
+ # 3. apples controlled (CV) vocab for template => Reuse
+ # 4. physics ontology (CV, ontology) => Reuse
+ # 5. New CV (CV List) List => New
+ # 6. New ontology List (CV List, ontology) => New
+ # New template attributes should be 6
+ # New sample controlled vocabs should be 2
+ ####################################################################################################################
+ template_json = fixture_file_upload('upload_json_sample_type_template/test_apple_cv_template.json', 'application/json')
+
+ assert_enqueued_jobs 1, only: PopulateTemplatesJob do
+ post :populate_template, params: { template_json_file: template_json }
+ end
+
+
+ assert_difference('Template.count', 1) do
+ assert_difference('TemplateAttribute.count', 6) do
+ assert_difference('SampleControlledVocab.count', 2) do
+ perform_enqueued_jobs(only: PopulateTemplatesJob)
+ end
+ end
+ end
+ registered_template = Template.last
+ assert_equal registered_template.template_attributes.detect { |ta| ta.title == 'apples controlled vocab for template' }.sample_controlled_vocab, apples_cv
+ assert_equal registered_template.template_attributes.detect { |ta| ta.title == 'physics ontology' }.sample_controlled_vocab, physics_ontology
+ end
+
+ test 'should allow controlled vocab attributes to have free text in instance-wide templates' do
+ login_as(@admin)
+ ####################################################################################################################
+ # This file contains the JSON definition for 1 template with 6 template attribute:
+ # 1. Source Name (Sting) => allowCVFreeText: null (not present)
+ # 2. Source Characteristic 1 (String) => allowCVFreeText: null
+ # 3. apples controlled vocab for template => allowCVFreeText: true
+ # 4. physics ontology (CV, ontology) => allowCVFreeText: false
+ # 5. New CV List (CV List) => allowCVFreeText: null => Should resolve to false
+ # 6. New ontology (CV List, ontology) => allowCVFreeText: null => Should resolve to false
+ ####################################################################################################################
+ template_json = fixture_file_upload('upload_json_sample_type_template/test_apple_cv_template.json', 'application/json')
+ assert_enqueued_jobs 1, only: PopulateTemplatesJob do
+ post :populate_template, params: { template_json_file: template_json }
+ end
+ assert_difference('Template.count', 1) do
+ assert_difference('TemplateAttribute.count', 6) do
+ perform_enqueued_jobs(only: PopulateTemplatesJob)
+ end
+ end
+
+ registered_template = Template.last
+ refute registered_template.template_attributes.detect { |ta| ta.title == 'Source Name' }.allow_cv_free_text
+ refute registered_template.template_attributes.detect { |ta| ta.title == 'Source Characteristic 1' }.allow_cv_free_text
+ assert registered_template.template_attributes.detect { |ta| ta.title == 'apples controlled vocab for template' }.allow_cv_free_text
+ refute registered_template.template_attributes.detect { |ta| ta.title == 'physics ontology' }.allow_cv_free_text
+ refute registered_template.template_attributes.detect { |ta| ta.title == 'New CV List' }.allow_cv_free_text
+ refute registered_template.template_attributes.detect { |ta| ta.title == 'New ontology List' }.allow_cv_free_text
+ end
+
def create_template_from_parent_template(parent_template, person= @person, linked_sample_type= nil)
child_template_attributes = parent_template.template_attributes.map do |ta|
FactoryBot.create(:template_attribute, parent_attribute_id: ta.id, title: ta.title, isa_tag_id: ta.isa_tag_id, sample_attribute_type: ta.sample_attribute_type, is_title: ta.is_title, required: ta.required, sample_controlled_vocab: ta.sample_controlled_vocab, pos: ta.pos)
diff --git a/test/unit/jobs/populate_templates_job_test.rb b/test/unit/jobs/populate_templates_job_test.rb
index 0558063667..8b91d8c7df 100644
--- a/test/unit/jobs/populate_templates_job_test.rb
+++ b/test/unit/jobs/populate_templates_job_test.rb
@@ -4,8 +4,8 @@ class PopulateTemplatesJobTest < ActiveSupport::TestCase
def setup
# Create the SampleAttributeTypes
# The title MUST be set manually!
- FactoryBot.create(:string_sample_attribute_type, title: 'String attribute type 1')
- FactoryBot.create(:sample_multi_sample_attribute_type, title: 'Sample multi attribute type 1')
+ FactoryBot.create(:string_sample_attribute_type, title: 'String') if SampleAttributeType.find_by(title: 'String').nil?
+ FactoryBot.create(:sample_multi_sample_attribute_type, title: 'Registered Sample List') if SampleAttributeType.find_by(title: 'Registered Sample List').nil?
# Create the ISA Tags
%i[source_isa_tag sample_isa_tag protocol_isa_tag source_characteristic_isa_tag sample_characteristic_isa_tag
@@ -16,6 +16,7 @@ def setup
# Set isa_json_compliance_enabled to true
Seek::Config.isa_json_compliance_enabled = true
+ @admin = FactoryBot.create(:admin)
end
def teardown
@@ -31,7 +32,7 @@ def teardown
assert_nothing_raised do
assert_difference('Template.count', 4) do
- PopulateTemplatesJob.perform_now
+ PopulateTemplatesJob.perform_now(@admin)
end
end
end
@@ -44,8 +45,8 @@ def teardown
assert_no_difference('Template.count') do
assert_raises(RuntimeError,
-'- The property \'#/data/0/data/1/dataType\' value \"Invalid String attribute type 1\" did not match one of the following values: String attribute type 1, Sample multi attribute type 1 in schema file:///home/kepel/projects/seek/lib/seek/isa_templates/template_attributes_schema_test.json#
- Could not find a Sample Attribute Type named \'Invalid String attribute type 1\'
') do
- PopulateTemplatesJob.perform_now
+'- The property \'#/data/0/data/1/dataType\' value \"Invalid String attribute type 1\" did not match one of the following values: ') do
+ PopulateTemplatesJob.perform_now(@admin)
end
end
end