diff --git a/Gemfile b/Gemfile index f0a3dfb3b..81f660188 100644 --- a/Gemfile +++ b/Gemfile @@ -12,7 +12,7 @@ gem "aws-sdk-sqs", "~> 1.3" gem "base32-url", "~> 0.3" gem "batch-loader", "~> 1.4", ">= 1.4.1" gem "bcrypt", "~> 3.1.7" -gem "bolognese", "~> 1.11.5" +gem "bolognese", "~> 2.0.0" gem "bootsnap", "~> 1.4", ">= 1.4.4", require: false gem "cancancan", "~> 3.0" gem "commonmarker", "~> 0.23.4" diff --git a/Gemfile.lock b/Gemfile.lock index f7c9a6f39..040c625be 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -113,7 +113,7 @@ GEM latex-decode (~> 0.0) binding_of_caller (1.0.0) debug_inspector (>= 0.0.1) - bolognese (1.11.5) + bolognese (2.0.0) activesupport (>= 4.2.5) benchmark_methods (~> 0.7) bibtex-ruby (>= 5.1.0) @@ -656,7 +656,7 @@ DEPENDENCIES bcrypt (~> 3.1.7) better_errors binding_of_caller - bolognese (~> 1.11.5) + bolognese (~> 2.0.0) bootsnap (~> 1.4, >= 1.4.4) bullet (~> 6.1) byebug @@ -749,4 +749,4 @@ DEPENDENCIES webmock (~> 3.1) BUNDLED WITH - 2.4.10 + 2.4.20 diff --git a/app/controllers/activities_controller.rb b/app/controllers/activities_controller.rb index e14a5059d..8b044b377 100644 --- a/app/controllers/activities_controller.rb +++ b/app/controllers/activities_controller.rb @@ -69,6 +69,9 @@ def index end, }.compact options[:is_collection] = true + options[:params] = { + publisher: params[:publisher], + } render json: ActivitySerializer.new(results, options).serialized_json, status: :ok @@ -105,6 +108,9 @@ def index }.compact options[:include] = @include options[:is_collection] = true + options[:params] = { + publisher: params[:publisher], + } render json: ActivitySerializer.new(results, options).serialized_json, status: :ok @@ -129,6 +135,9 @@ def show options = {} options[:include] = @include options[:is_collection] = false + options[:params] = { + publisher: params[:publisher], + } render json: ActivitySerializer.new(@activity, options).serialized_json, status: :ok diff --git a/app/controllers/datacite_dois_controller.rb b/app/controllers/datacite_dois_controller.rb index 57a55db5a..5a4270a3f 100644 --- a/app/controllers/datacite_dois_controller.rb +++ b/app/controllers/datacite_dois_controller.rb @@ -196,6 +196,7 @@ def index current_ability: current_ability, detail: params[:detail], affiliation: params[:affiliation], + publisher: params[:publisher], is_collection: options[:is_collection], } @@ -339,6 +340,7 @@ def index detail: params[:detail], composite: params[:composite], affiliation: params[:affiliation], + publisher: params[:publisher], # The cursor link should be an array of values, but we want to encode it into a single string for the URL "page[cursor]" => page[:cursor] ? make_cursor(results) : nil, @@ -359,6 +361,7 @@ def index detail: params[:detail], composite: params[:composite], affiliation: params[:affiliation], + publisher: params[:publisher], is_collection: options[:is_collection], } @@ -459,6 +462,7 @@ def show detail: true, composite: nil, affiliation: params[:affiliation], + publisher: params[:publisher], } render json: DataciteDoiSerializer.new(doi, options).serialized_json, @@ -511,7 +515,11 @@ def validate options = {} options[:include] = @include options[:is_collection] = false - options[:params] = { current_ability: current_ability } + options[:params] = { + current_ability: current_ability, + affiliation: params[:affiliation], + publisher: params[:publisher] + } render json: DataciteDoiSerializer.new(@doi, options).serialized_json, status: :ok @@ -539,6 +547,7 @@ def create current_ability: current_ability, detail: true, affiliation: params[:affiliation], + publisher: params[:publisher], } render json: DataciteDoiSerializer.new(@doi, options).serialized_json, @@ -597,6 +606,7 @@ def update current_ability: current_ability, detail: true, affiliation: params[:affiliation], + publisher: params[:publisher], } render json: DataciteDoiSerializer.new(@doi, options).serialized_json, diff --git a/app/graphql/types/doi_item.rb b/app/graphql/types/doi_item.rb index d4a772436..6e2fdf89e 100644 --- a/app/graphql/types/doi_item.rb +++ b/app/graphql/types/doi_item.rb @@ -579,6 +579,17 @@ def identifiers end end + def publisher + case object.publisher + when Hash + object.publisher["name"] + when String + object.publisher + else + object.publisher + end + end + def bibtex pages = if object.container.to_h["firstPage"].present? @@ -909,7 +920,7 @@ def citeproc_hsh "volume" => object.container.to_h["volume"], "issue" => object.container.to_h["issue"], "page" => page, - "publisher" => object.publisher, + "publisher" => (object.publisher.is_a?(Hash) ? object.publisher&.fetch("name", nil) : object.publisher), "title" => parse_attributes(object.titles, content: "title", first: true), "URL" => object.url, "version" => object.version_info, diff --git a/app/jobs/doi_convert_publisher_by_id_job.rb b/app/jobs/doi_convert_publisher_by_id_job.rb new file mode 100644 index 000000000..7e839db35 --- /dev/null +++ b/app/jobs/doi_convert_publisher_by_id_job.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +class DoiConvertPublisherByIdJob < ApplicationJob + queue_as :lupo_background + + rescue_from ActiveJob::DeserializationError, + Elasticsearch::Transport::Transport::Errors::BadRequest do |error| + Rails.logger.error error.message + end + + def perform(options = {}) + Doi.convert_publisher_by_id(options) + end +end diff --git a/app/lib/params_sanitizer.rb b/app/lib/params_sanitizer.rb index b90b24820..6d912b1b4 100644 --- a/app/lib/params_sanitizer.rb +++ b/app/lib/params_sanitizer.rb @@ -35,6 +35,15 @@ class ParamsSanitizer :titles, { titles: %i[title titleType lang] }, :publisher, + { + publisher: %i[ + name + publisherIdentifier + publisherIdentifierScheme + schemeUri + lang + ], + }, :publicationYear, :created, :prefix, diff --git a/app/models/doi.rb b/app/models/doi.rb index 599af8e39..35f99d961 100644 --- a/app/models/doi.rb +++ b/app/models/doi.rb @@ -4,7 +4,8 @@ require "benchmark" class Doi < ApplicationRecord - audited only: %i[doi url creators contributors titles publisher publication_year types descriptions container sizes formats version_info language dates identifiers related_identifiers related_items funding_references geo_locations rights_list subjects schema_version content_url landing_page aasm_state source reason] + PUBLISHER_JSON_SCHEMA = "#{Rails.root}/app/models/schemas/doi/publisher.json" + audited only: %i[doi url creators contributors titles publisher publisher_obj publication_year types descriptions container sizes formats version_info language dates identifiers related_identifiers related_items funding_references geo_locations rights_list subjects schema_version content_url landing_page aasm_state source reason] # disable STI self.inheritance_column = :_type_disabled @@ -103,6 +104,17 @@ class Doi < ApplicationRecord validates_presence_of :doi validates_presence_of :url, if: Proc.new { |doi| doi.is_registered_or_findable? } + json_schema_validation = { + message: ->(errors) { errors }, + schema: PUBLISHER_JSON_SCHEMA + } + + def validate_publisher_obj?(doi) + doi.validatable? && doi.publisher_obj? && !(doi.publisher.blank? || doi.publisher.all?(nil)) + end + + validates :publisher_obj, if: ->(doi) { validate_publisher_obj?(doi) }, json: json_schema_validation + # from https://www.crossref.org/blog/dois-and-matching-regular-expressions/ but using uppercase validates_format_of :doi, with: /\A10\.\d{4,5}\/[-._;()\/:a-zA-Z0-9*~$=]+\z/, on: :create validates_format_of :url, with: /\A(ftp|http|https):\/\/\S+/, if: :url?, message: "URL is not valid" @@ -117,6 +129,7 @@ class Doi < ApplicationRecord validate :check_descriptions, if: :descriptions? validate :check_types, if: :types? validate :check_container, if: :container? + validate :check_publisher, if: :publisher? validate :check_subjects, if: :subjects? validate :check_creators, if: :creators? validate :check_contributors, if: :contributors? @@ -131,6 +144,7 @@ class Doi < ApplicationRecord after_commit :update_url, on: %i[create update] after_commit :update_media, on: %i[create update] + before_validation :update_publisher, if: [ :will_save_change_to_publisher?, :publisher? ] before_validation :update_xml, if: :regenerate before_validation :update_agency before_validation :update_field_of_science @@ -565,7 +579,7 @@ def as_indexed_json(_options = {}) "creator_names" => creator_names, "titles" => Array.wrap(titles), "descriptions" => Array.wrap(descriptions), - "publisher" => publisher, + "publisher" => publisher && publisher["name"], "client_id" => client_id, "provider_id" => provider_id, "consortium_id" => consortium_id, @@ -1452,6 +1466,45 @@ def self.convert_affiliation_by_id(options = {}) count end + def self.convert_publishers(options = {}) + from_id = (options[:from_id] || Doi.minimum(:id)).to_i + until_id = (options[:until_id] || Doi.maximum(:id)).to_i + + # get every id between from_id and until_id + (from_id..until_id).step(500).each do |id| + DoiConvertPublisherByIdJob.perform_later(options.merge(id: id)) + Rails.logger.info "Queued converting publisher to publisher_obj for DOIs with IDs starting with #{id}." unless Rails.env.test? + end + + "Queued converting #{(from_id..until_id).size} publishers." + end + + def self.convert_publisher_by_id(options = {}) + return nil if options[:id].blank? + + id = options[:id].to_i + count = 0 + + Doi.where(id: id..(id + 499)).find_each do |doi| + should_update = true + + if should_update + Doi.auditing_enabled = false + doi.update_columns(publisher_obj: doi.publisher) + Doi.auditing_enabled = true + + count += 1 + end + end + + Rails.logger.info "[MySQL] Converted publishers for #{count} DOIs with IDs #{id} - #{id + 499}." if count > 0 + + count + rescue TypeError, ActiveRecord::ActiveRecordError, ActiveRecord::LockWaitTimeout => e + Rails.logger.error "[MySQL] Error converting publishers for DOIs with IDs #{id} - #{id + 499}: #{e.message}." + count + end + def self.convert_containers(options = {}) from_id = (options[:from_id] || Doi.minimum(:id)).to_i until_id = (options[:until_id] || Doi.maximum(:id)).to_i @@ -1901,6 +1954,10 @@ def check_container errors.add(:container, "Container '#{container}' should be an object instead of a string.") unless container.is_a?(Hash) end + def check_publisher + errors.add(:publisher, "Publisher '#{publisher}' should be an object instead of a string.") unless publisher.is_a?(Hash) + end + def check_language errors.add(:language, "Language #{language} is in an invalid format.") if !language.match?(/^[a-zA-Z]{1,8}(-[a-zA-Z0-9]{1,8})*$/) end @@ -2230,6 +2287,30 @@ def update_types ).compact end + def update_publisher + case publisher_before_type_cast + when Hash + update_publisher_from_hash + when String + update_publisher_from_string + else + reset_publishers + end + end + + def publisher + pub = read_attribute("publisher") + pub_obj = read_attribute("publisher_obj") + + return nil if pub.nil? && pub_obj.nil? + + if !(pub_obj.nil? || pub_obj.empty?) + pub_obj + else + { "name" => pub || "" } + end + end + def self.repair_landing_page(id: nil) if id.blank? Rails.logger.error "[Error] No id provided." @@ -2368,7 +2449,6 @@ def self.add_index_type(options = {}) "Finished updating dois, total #{count}" end - # QUICK FIX UNTIL PROJECT IS A RESOURCE_TYPE_GENERAL IN THE SCHEMA def handle_resource_type(types) if types.present? && types["resourceType"] == "Project" && (types["resourceTypeGeneral"] == "Text" || types["resourceTypeGeneral"] == "Other") @@ -2377,4 +2457,30 @@ def handle_resource_type(types) types.to_h["resourceTypeGeneral"] end end + + private + def update_publisher_from_hash + if !publisher_before_type_cast.values.all?(nil) + self.publisher_obj = { + name: publisher_before_type_cast.fetch(:name, nil), + lang: publisher_before_type_cast.fetch(:lang, nil), + schemeUri: publisher_before_type_cast.fetch(:schemeUri, nil), + publisherIdentifier: publisher_before_type_cast.fetch(:publisherIdentifier, nil), + publisherIdentifierScheme: publisher_before_type_cast.fetch(:publisherIdentifierScheme, nil) + }.compact + self.publisher = publisher_before_type_cast.dig(:name) + else + reset_publishers + end + end + + def update_publisher_from_string + self.publisher_obj = { name: publisher_before_type_cast } + self.publisher = publisher_before_type_cast + end + + def reset_publishers + self.publisher_obj = nil + self.publisher = nil + end end diff --git a/app/models/schemas/doi/publisher.json b/app/models/schemas/doi/publisher.json new file mode 100644 index 000000000..6a1c76b6a --- /dev/null +++ b/app/models/schemas/doi/publisher.json @@ -0,0 +1,12 @@ +{ + "type": "object", + "$schema": "http://json-schema.org/draft-04/schema#", + "properties": { + "name": { "type": "string" }, + "publisherIdentifier": { "type": "string" }, + "publisherIdentifierScheme": { "type": "string" }, + "schemeUri": { "type": "string" }, + "lang": { "type": "string" } + }, + "additionalProperties": false +} diff --git a/app/serializers/activity_serializer.rb b/app/serializers/activity_serializer.rb index 45f4e4093..99c14cc1b 100644 --- a/app/serializers/activity_serializer.rb +++ b/app/serializers/activity_serializer.rb @@ -11,8 +11,59 @@ class ActivitySerializer "prov:wasDerivedFrom", "prov:wasAttributedTo", :action, - :version, - :changes + :version + + attribute :changes do |object, params| + changes = object._source.changes + pub = changes.publisher + pub_obj = changes.publisher_obj + + ret = changes + + if object._source.action == "update" + if pub || pub_obj + if params[:publisher] == "true" + if !pub_obj + changes.publisher = + [ + { "name": pub[0] }, + { "name": pub[1] }, + ] + else + changes.publisher = changes.publisher_obj + end + else + if !pub + changes.publisher = [ pub_obj[0].name, pub_obj[1].name ] + end + end + + ret = changes + end + elsif object._source.action == "create" + if pub || pub_obj + if params[:publisher] == "true" + if !pub_obj + changes.publisher = { "name": pub } + else + changes.publisher = changes.publisher_obj + end + else + if !pub + changes.publisher = pub_obj.name + end + end + + ret = changes + end + end + + if pub_obj + changes.delete("publisher_obj") + end + + ret + end attribute "prov:wasDerivedFrom", &:was_derived_from diff --git a/app/serializers/datacite_doi_serializer.rb b/app/serializers/datacite_doi_serializer.rb index 36c897f28..b47af8753 100644 --- a/app/serializers/datacite_doi_serializer.rb +++ b/app/serializers/datacite_doi_serializer.rb @@ -118,6 +118,27 @@ class DataciteDoiSerializer attribute :doi, &:uid + attribute :publisher do |object, params| + # new - format obj only if ?publisher=true, otherwise serialize the old format (a string) + if object.publisher.nil? + nil + else + if params&.dig(:publisher) == "true" + if object.publisher.respond_to?(:to_hash) + object.publisher + else + { "name" => object.publisher } + end + else + if object.publisher.respond_to?(:to_hash) + object.publisher["name"] + else + object.publisher + end + end + end + end + attribute :creators do |object, params| # Always return an array of creators and affiliations # use new array format only if affiliation param present diff --git a/app/serializers/work_serializer.rb b/app/serializers/work_serializer.rb index 7474791c4..9a295268b 100644 --- a/app/serializers/work_serializer.rb +++ b/app/serializers/work_serializer.rb @@ -67,7 +67,13 @@ class WorkSerializer Array.wrap(object.descriptions).first.to_h.fetch("description", nil) end - attribute :container_title, &:publisher + attribute :container_title do |object| + if object.publisher.respond_to?(:to_hash) + object.publisher["name"] + elsif object.publisher.respond_to?(:to_str) + object.publisher + end + end attribute :resource_type_subtype do |object| object.types.to_h.fetch("resourceType", nil) diff --git a/lib/tasks/doi.rake b/lib/tasks/doi.rake index 12edc6677..828aafc9b 100644 --- a/lib/tasks/doi.rake +++ b/lib/tasks/doi.rake @@ -245,6 +245,14 @@ namespace :doi do puts Doi.convert_affiliations(from_id: from_id, until_id: until_id) end + desc "Convert publishers to new format" + task convert_publishers: :environment do + from_id = (ENV["FROM_ID"] || Doi.minimum(:id)).to_i + until_id = (ENV["UNTIL_ID"] || Doi.maximum(:id)).to_i + + puts Doi.convert_publishers(from_id: from_id, until_id: until_id) + end + desc "Convert containers to new format" task convert_containers: :environment do from_id = (ENV["FROM_ID"] || Doi.minimum(:id)).to_i diff --git a/spec/concerns/crosscitable_spec.rb b/spec/concerns/crosscitable_spec.rb index e9a41ef42..5491e5831 100644 --- a/spec/concerns/crosscitable_spec.rb +++ b/spec/concerns/crosscitable_spec.rb @@ -199,7 +199,11 @@ ) expect(meta["titles"]).to eq([{ "title" => "Eating your own Dog Food" }]) expect(meta["publication_year"]).to eq("2016") - expect(meta["publisher"]).to eq("DataCite") + expect(meta["publisher"]).to eq( + { + "name" => "DataCite" + } + ) end it "from schema 3" do @@ -222,7 +226,11 @@ [{ "title" => "Data from: A new malaria agent in African hominids." }], ) expect(meta["publication_year"]).to eq("2011") - expect(meta["publisher"]).to eq("Dryad Digital Repository") + expect(meta["publisher"]).to eq( + { + "name" => "Dryad Digital Repository" + } + ) end it "from schema 2.2" do @@ -263,7 +271,11 @@ ], ) expect(meta["publication_year"]).to eq("2010") - expect(meta["publisher"]).to eq("Springer") + expect(meta["publisher"]).to eq( + { + "name" => "Springer" + } + ) end it "from schema 4 missing creators" do @@ -276,7 +288,11 @@ expect(meta["creators"]).to be_empty expect(meta["titles"]).to eq([{ "title" => "Eating your own Dog Food" }]) expect(meta["publication_year"]).to eq("2016") - expect(meta["publisher"]).to eq("DataCite") + expect(meta["publisher"]).to eq( + { + "name" => "DataCite" + } + ) end it "from namespaced xml" do @@ -322,7 +338,11 @@ ], ) expect(meta["publication_year"]).to eq("2014") - expect(meta["publisher"]).to eq("eLife Sciences Publications, Ltd") + expect(meta["publisher"]).to eq( + { + "name" => "eLife Sciences Publications, Ltd" + } + ) expect(meta["container"]).to eq( "firstPage" => "e01567", "identifier" => "2050-084X", @@ -361,7 +381,11 @@ ], ) expect(meta["publication_year"]).to eq("2014") - expect(meta["publisher"]).to eq("eLife Sciences Publications, Ltd") + expect(meta["publisher"]).to eq( + { + "name" => "eLife Sciences Publications, Ltd" + } + ) expect(meta["container"]).to eq( "firstPage" => "e01567", "identifier" => "2050-084X", @@ -421,7 +445,11 @@ ], ) expect(meta["publication_year"]).to eq("2014") - expect(meta["publisher"]).to eq("{eLife} Sciences Organisation, Ltd.") + expect(meta["publisher"]).to eq( + { + "name" => "{eLife} Sciences Organisation, Ltd." + } + ) expect(meta["container"]).to eq( "identifier" => "2050-084X", "identifierType" => "ISSN", @@ -456,7 +484,11 @@ ], ) expect(meta["publication_year"]).to eq("2014") - expect(meta["publisher"]).to eq("(:unav)") + expect(meta["publisher"]).to eq( + { + "name" => "(:unav)" + } + ) expect(meta["container"]).to eq( "title" => "eLife", "type" => "Journal", "volume" => "3", ) @@ -488,7 +520,11 @@ [{ "title" => "R Interface to the DataONE REST API" }], ) expect(meta["publication_year"]).to eq("2016") - expect(meta["publisher"]).to eq("https://cran.r-project.org") + expect(meta["publisher"]).to eq( + { + "name" => "https://cran.r-project.org" + } + ) end it "from schema_org" do @@ -514,7 +550,11 @@ ) expect(meta["titles"]).to eq([{ "title" => "Eating your own Dog Food" }]) expect(meta["publication_year"]).to eq("2016") - expect(meta["publisher"]).to eq("DataCite") + expect(meta["publisher"]).to eq( + { + "name" => "DataCite" + } + ) end it "from schema_org url" do @@ -540,7 +580,11 @@ ], ) expect(meta["publication_year"]).to eq("2014") - expect(meta["publisher"]).to eq("PANGAEA") + expect(meta["publisher"]).to eq( + { + "name" => "PANGAEA" + } + ) expect(meta["schema_version"]).to eq(nil) end end @@ -576,7 +620,11 @@ [{ "title" => "Data from: A new malaria agent in African hominids." }], ) expect(meta["publication_year"]).to eq("2011") - expect(meta["publisher"]).to eq("Dryad Digital Repository") + expect(meta["publisher"]).to eq( + { + "name" => "Dryad Digital Repository" + } + ) end it "from schema 2.2" do @@ -615,7 +663,11 @@ ], ) expect(meta["publication_year"]).to eq("2010") - expect(meta["publisher"]).to eq("Springer") + expect(meta["publisher"]).to eq( + { + "name" => "Springer" + } + ) end it "from schema 4 missing creators" do @@ -626,7 +678,11 @@ expect(meta["creators"]).to be_empty expect(meta["titles"]).to eq([{ "title" => "Eating your own Dog Food" }]) expect(meta["publication_year"]).to eq("2016") - expect(meta["publisher"]).to eq("DataCite") + expect(meta["publisher"]).to eq( + { + "name" => "DataCite" + } + ) end it "from crossref" do @@ -656,7 +712,11 @@ ], ) expect(meta["publication_year"]).to eq("2014") - expect(meta["publisher"]).to eq("eLife Sciences Publications, Ltd") + expect(meta["publisher"]).to eq( + { + "name" => "eLife Sciences Publications, Ltd" + } + ) expect(meta["container"]).to eq( "firstPage" => "e01567", "identifier" => "2050-084X", @@ -688,7 +748,11 @@ ], ) expect(meta["publication_year"]).to eq("2014") - expect(meta["publisher"]).to eq("{eLife} Sciences Organisation, Ltd.") + expect(meta["publisher"]).to eq( + { + "name" => "{eLife} Sciences Organisation, Ltd." + } + ) expect(meta["container"]).to eq( "identifier" => "2050-084X", "identifierType" => "ISSN", @@ -721,7 +785,11 @@ ], ) expect(meta["publication_year"]).to eq("2014") - expect(meta["publisher"]).to eq("(:unav)") + expect(meta["publisher"]).to eq( + { + "name" => "(:unav)" + } + ) expect(meta["container"]).to eq( "title" => "eLife", "type" => "Journal", "volume" => "3", ) @@ -751,7 +819,11 @@ [{ "title" => "R Interface to the DataONE REST API" }], ) expect(meta["publication_year"]).to eq("2016") - expect(meta["publisher"]).to eq("https://cran.r-project.org") + expect(meta["publisher"]).to eq( + { + "name" => "https://cran.r-project.org" + } + ) end it "from schema_org" do @@ -775,7 +847,11 @@ ) expect(meta["titles"]).to eq([{ "title" => "Eating your own Dog Food" }]) expect(meta["publication_year"]).to eq("2016") - expect(meta["publisher"]).to eq("DataCite") + expect(meta["publisher"]).to eq( + { + "name" => "DataCite" + } + ) end end end diff --git a/spec/factories/doi.rb b/spec/factories/doi.rb index 29a50d86b..708cd6d53 100644 --- a/spec/factories/doi.rb +++ b/spec/factories/doi.rb @@ -90,7 +90,13 @@ descriptions do [{ "description": "Data from: A new malaria agent in African hominids." }] end - publisher { "Dryad Digital Repository" } + publisher { { + "name": "Dryad Digital Repository", + "publisherIdentifier": "https://ror.org/00x6h5n95", + "publisherIdentifierScheme": "ROR", + "schemeUri": "https://ror.org/", + "lang": "en" + } } subjects do [ { "subject": "Phylogeny" }, diff --git a/spec/fixtures/files/datacite-example-full-v4.5.xml b/spec/fixtures/files/datacite-example-full-v4.5.xml new file mode 100644 index 000000000..b6642a58f --- /dev/null +++ b/spec/fixtures/files/datacite-example-full-v4.5.xml @@ -0,0 +1,255 @@ + + + + 10.82433/B09Z-4K37 + + + ExampleFamilyName, ExampleGivenName + ExampleGivenName + ExampleFamilyName + https://orcid.org/0000-0001-5727-2427 + ExampleAffiliation + + + ExampleOrganization + https://ror.org/04wxnsj81 + + + + Example Title + Example Subtitle + Example TranslatedTitle + Example AlternativeTitle + + Example Publisher + 2023 + Example ResourceType + + FOS: Computer and information sciences + Digital curation and preservation + Example Subject + + + + ExampleFamilyName, ExampleGivenName + ExampleGivenName + ExampleFamilyName + https://orcid.org/0000-0001-5727-2427/ + ExampleAffiliation + + + ExampleFamilyName, ExampleGivenName + + + ExampleFamilyName, ExampleGivenName + + + ExampleFamilyName, ExampleGivenName + + + ExampleOrganization + + + ExampleFamilyName, ExampleGivenName + + + ExampleOrganization + + + ExampleFamilyName, ExampleGivenName + + + ExampleFamilyName, ExampleGivenName + + + ExampleFamilyName, ExampleGivenName + + + ExampleFamilyName, ExampleGivenName + + + DataCite + + + International DOI Foundation + + + ExampleFamilyName, ExampleGivenName + + + ExampleFamilyName, ExampleGivenName + + + ExampleContributor + + + ExampleFamilyName, ExampleGivenName + + + ExampleContributor + + + ExampleFamilyName, ExampleGivenName + + + ExampleOrganization + + + ExampleFamilyName, ExampleGivenName + + + + 2023-01-01 + 2023-01-01 + 2023-01-01 + 2022-01-01/2022-12-31 + 2023-01-01 + 2023-01-01 + 2023-01-01 + 2023-01-01 + 2023-01-01 + 2023-01-01 + 2023-01-01 + + en + + 12345 + + + ark:/13030/tqb3kh97gh8w + arXiv:0706.0001 + 2018AGUFM.A24K..07S + 10.1016/j.epsl.2011.11.037 + 9783468111242 + 1562-6865 + 10013/epic.10033 + IECUR0097 + 978-3-905673-82-1 + 0077-5606 + 0A9 2002 12B4A105 7 + 1188-1534 + urn:lsid:ubio.org:namebank:11815 + 12082125 + http://purl.oclc.org/foo/bar + 123456789999 + http://www.heatflow.und.edu/index2.html + urn:nbn:de:101:1-201102033592 + https://w3id.org/games/spec/coil#Coil_Bomb_Die_Of_Age + 10.1016/j.epsl.2011.11.037 + 10.1016/j.epsl.2011.11.037 + 10.1016/j.epsl.2011.11.037 + 10.1016/j.epsl.2011.11.037 + 10.1016/j.epsl.2011.11.037 + 10.1016/j.epsl.2011.11.037 + 10.1016/j.epsl.2011.11.037 + 10.1016/j.epsl.2011.11.037 + 10.1016/j.epsl.2011.11.037 + 10.1016/j.epsl.2011.11.037 + 10.1016/j.epsl.2011.11.037 + 10.1016/j.epsl.2011.11.037 + 10.1016/j.epsl.2011.11.037 + 10.1016/j.epsl.2011.11.037 + 10.1016/j.epsl.2011.11.037 + 10.1016/j.epsl.2011.11.037 + 10.1016/j.epsl.2011.11.037 + + + 1 MB + 90 pages + + + application/xml + text/plain + + 1 + + Creative Commons Attribution 4.0 International + + + Example Abstract + Example Methods + Example SeriesInformation + Example TableOfContents + Example TechnicalInfo + Example Other + + + + Vancouver, British Columbia, Canada + + 49.2827 + -123.1207 + + + -123.27 + -123.02 + 49.195 + 49.315 + + + + 41.991 + -71.032 + + + 42.893 + -69.622 + + + 41.991 + -68.211 + + + 41.090 + -69.622 + + + 41.991 + -71.032 + + + + + + + Example Funder + https://doi.org/10.13039/501100000780 + 12345 + Example AwardTitle + + + + + 1234-5678 + + + ExampleFamilyName, ExampleGivenName + ExampleGivenName + ExampleFamilyName + + + + Example RelatedItem Title + Example RelatedItem TranslatedTitle + + 1990 + 1 + 2 + 1 + 1 + 100 + Example RelatedItem Publisher + Example RelatedItem Edition + + + ExampleFamilyName, ExampleGivenName + ExampleGivenName + ExampleFamilyName + + + + + + \ No newline at end of file diff --git a/spec/graphql/types/work_type_spec.rb b/spec/graphql/types/work_type_spec.rb index 3a1c53e51..ce2467845 100644 --- a/spec/graphql/types/work_type_spec.rb +++ b/spec/graphql/types/work_type_spec.rb @@ -58,6 +58,7 @@ identifierType title } + publisher bibtex xml schemaOrg @@ -90,6 +91,9 @@ expect(response.dig("data", "work", "id")).to eq( "https://handle.stage.datacite.org/#{work.doi.downcase}", ) + expect(response.dig("data", "work", "publisher")).to eq( + "Dryad Digital Repository", + ) bibtex = BibTeX.parse(response.dig("data", "work", "bibtex")).to_a(quotes: ""). @@ -331,6 +335,7 @@ nodes { id doi + publisher creators{ type } @@ -514,6 +519,9 @@ expect( response.dig("data", "works", "nodes", 0, "creators", 1, "type"), ).to be nil + expect( + response.dig("data", "works", "nodes", 0, "publisher"), + ).to eq("Dryad Digital Repository") end_cursor = response.dig("data", "works", "pageInfo", "endCursor") response = diff --git a/spec/models/doi_spec.rb b/spec/models/doi_spec.rb index c74323ae6..515357dd5 100644 --- a/spec/models/doi_spec.rb +++ b/spec/models/doi_spec.rb @@ -1210,6 +1210,16 @@ expect(subject.publication_year).to eq(2011) end + it "publisher" do + expect(subject.publisher).to eq({ + "name" => "Dryad Digital Repository", + "publisherIdentifier" => "https://ror.org/00x6h5n95", + "publisherIdentifierScheme" => "ROR", + "schemeUri" => "https://ror.org/", + "lang" => "en" + }) + end + it "schema_version" do expect(subject.schema_version).to eq("http://datacite.org/schema/kernel-4") end @@ -1265,7 +1275,7 @@ end it "publisher" do - expect(subject.publisher).to eq(publisher) + expect(subject.publisher).to eq({ "name" => publisher }) xml = Maremma.from_xml(subject.xml).fetch("resource", {}) expect(xml.dig("publisher")).to eq(publisher) diff --git a/spec/requests/activities_spec.rb b/spec/requests/activities_spec.rb index 84f184c4c..5af98fdea 100644 --- a/spec/requests/activities_spec.rb +++ b/spec/requests/activities_spec.rb @@ -178,4 +178,60 @@ end end end + + describe "query activities - when the publisher param is not 'true'", elasticsearch: true do + let!(:doi) { create(:doi, client: client) } + let!(:other_doi) { create(:doi, client: client) } + + before do + DataciteDoi.import + Activity.import + sleep 2 + end + + context "query by doi" do + it "returns the activities" do + get "/activities?datacite-doi-id=#{doi.doi.downcase}", + nil, headers + + expect(last_response.status).to eq(200) + expect(json.dig("data").length).to eq(1) + expect(json.dig("meta", "total")).to eq(1) + expect(json.dig("data", 0, "attributes", "action")).to eq("create") + expect(json.dig("data", 0, "attributes", "changes", "publisher")).to eq("Dryad Digital Repository") + end + end + end + + describe "query activities - when the publisher param is set to true", elasticsearch: true do + let!(:doi) { create(:doi, client: client) } + let!(:other_doi) { create(:doi, client: client) } + + before do + DataciteDoi.import + Activity.import + sleep 2 + end + + context "query by doi" do + it "returns the activities" do + get "/activities?publisher=true&datacite-doi-id=#{doi.doi.downcase}", + nil, headers + + expect(last_response.status).to eq(200) + expect(json.dig("data").length).to eq(1) + expect(json.dig("meta", "total")).to eq(1) + expect(json.dig("data", 0, "attributes", "action")).to eq("create") + expect(json.dig("data", 0, "attributes", "changes", "publisher")).to eq( + { + "lang" => "en", + "name" => "Dryad Digital Repository", + "schemeUri" => "https://ror.org/", + "publisherIdentifier" => "https://ror.org/00x6h5n95", + "publisherIdentifierScheme" => "ROR" + } + ) + end + end + end end diff --git a/spec/requests/datacite_dois_spec.rb b/spec/requests/datacite_dois_spec.rb index 7d6984039..173678009 100755 --- a/spec/requests/datacite_dois_spec.rb +++ b/spec/requests/datacite_dois_spec.rb @@ -224,6 +224,59 @@ next_link = next_link_absolute.path + "?" + next_link_absolute.query expect(next_link).to eq("/dois?fields%5Bdois%5D=id%2Csubjects&page%5Bnumber%5D=2&page%5Bsize%5D=2") end + + it "returns publisher objects when publisher param is set to true" do + get "/dois?publisher=true", nil, headers + + expect(last_response.status).to eq(200) + json["data"].each do |doi| + expect(doi.dig("attributes", "publisher")).to eq( + { + "name" => "Dryad Digital Repository", + } + ) + end + end + end + + describe "GET /dois with nil publisher values", elasticsearch: true do + let!(:doi) { create(:doi, client: client, publisher: nil) } + + it "returns nil publisher when publisher param is not set" do + get "/dois", nil, headers + + expect(last_response.status).to eq(200) + json["data"].each do |doi| + expect(doi.dig("attributes", "publisher")).to eq(nil) + end + end + + it "returns nil publisher when publisher param is set to true" do + get "/dois?publisher=true", nil, headers + + expect(last_response.status).to eq(200) + json["data"].each do |doi| + expect(doi.dig("attributes", "publisher")).to eq(nil) + end + end + end + + describe "GET /dois/:id with nil publisher values", elasticsearch: true do + let!(:doi) { create(:doi, client: client, publisher: nil) } + + it "returns nil publisher when publisher param is not set" do + get "/dois/#{doi.doi}", nil, headers + + expect(last_response.status).to eq(200) + expect(json.dig("attributes", "publisher")).to eq(nil) + end + + it "returns nil publisher when publisher param is set to true" do + get "/dois/#{doi.doi}?publisher=true", nil, headers + + expect(last_response.status).to eq(200) + expect(json.dig("attributes", "publisher")).to eq(nil) + end end describe "GET /dois with filter", elasticsearch: true do @@ -589,6 +642,29 @@ expect(json.dig("data", "attributes", "creators", 0, "nameIdentifiers")).to eq([{ "nameIdentifier" => "http://viaf.org/viaf/4934600", "nameIdentifierScheme" => "VIAF" }]) end end + + context "when the publisher param is set to true" do + it "returns the Doi" do + get "/dois/#{doi.doi}?publisher=true", nil, headers + + expect(last_response.status).to eq(200) + result = json.dig("data") + + expect(result.dig("attributes", "doi")).to eq(doi.doi.downcase) + expect(result.dig("attributes", "titles")).to eq(doi.titles) + expect(result.dig("attributes", "identifiers")).to eq([{ "identifier" => "pk-1234", "identifierType" => "publisher ID" }]) + expect(result.dig("attributes", "alternateIdentifiers")).to eq([{ "alternateIdentifier" => "pk-1234", "alternateIdentifierType" => "publisher ID" }]) + expect(result.dig("attributes", "publisher")).to eq( + { + "name" => "Dryad Digital Repository", + "publisherIdentifier" => "https://ror.org/00x6h5n95", + "publisherIdentifierScheme" => "ROR", + "schemeUri" => "https://ror.org/", + "lang" => "en" + } + ) + end + end end describe "GET /dois for dissertations", elasticsearch: true, vcr: true do @@ -1936,6 +2012,12 @@ doc = Nokogiri::XML(Base64.decode64(json.dig("data", "attributes", "xml")), nil, "UTF-8", &:noblanks) expect(doc.at_css("identifier").content).to eq("10.14454/10703") + + expect(Doi.where(doi: "10.14454/10703").first.publisher).to eq( + { + "name" => "DataCite" + } + ) end end @@ -2299,7 +2381,7 @@ "name" => "Miller, Elizabeth", "nameIdentifiers" => [{ "nameIdentifier" => "https://orcid.org/0000-0001-5000-0007", "nameIdentifierScheme" => "ORCID", "schemeUri" => "https://orcid.org" }], "nameType" => "Personal") - expect(json.dig("data", "attributes", "creators")[1]).to eq("affiliation" => [{ "affiliationIdentifierScheme" => "ROR", "affiliationIdentifier" => "https://ror.org/05gq02987", "name" => "Brown University" }, { "affiliationIdentifierScheme" => "GRID", "affiliationIdentifier" => "https://grid.ac/institutes/grid.268117.b", "name" => "Wesleyan University", "schemeUri" => "https://grid.ac/institutes/" }], + expect(json.dig("data", "attributes", "creators")[1]).to eq("affiliation" => [{ "affiliationIdentifierScheme" => "ROR", "affiliationIdentifier" => "https://ror.org/05gq02987", "name" => "Brown University" }, { "affiliationIdentifierScheme" => "GRID", "affiliationIdentifier" => "https://grid.ac/institutes/grid.268117.b", "schemeUri" => "https://grid.ac/institutes/", "name" => "Wesleyan University" }], "familyName" => "Carberry", "givenName" => "Josiah", "name" => "Carberry, Josiah", @@ -2560,7 +2642,6 @@ it "updates the record" do patch "/dois/10.14454/8na3-9s47", valid_attributes, headers - p json expect(last_response.status).to eq(201) expect(json.dig("data", "attributes", "url")).to eq("https://ors.datacite.org/doi:/10.14454/8na3-9s47") expect(json.dig("data", "attributes", "doi")).to eq("10.14454/8na3-9s47") @@ -2883,6 +2964,156 @@ end end + context "when the request uses schema 4.5" do + let(:xml) { Base64.strict_encode64(file_fixture("datacite-example-full-v4.5.xml").read) } + let(:doi) { "10.14454/10703" } + let(:valid_attributes) do + { + "data" => { + "type" => "dois", + "attributes" => { + "doi" => doi, + "url" => "http://www.bl.uk/pdf/patspec.pdf", + "xml" => xml, + "event" => "publish", + }, + }, + } + end + + it "creates a Doi" do + post "/dois", valid_attributes, headers + pp json + + expect(last_response.status).to eq(201) + expect(json.dig("data", "attributes", "doi")).to eq(doi) + expect(json.dig("data", "attributes", "schemaVersion")).to eq("http://datacite.org/schema/kernel-4") + expect(json.dig("data", "attributes", "state")).to eq("findable") + expect(json.dig("data", "attributes", "publisher")).to eq("Example Publisher") + expect(json.dig("data", "attributes", "relatedIdentifiers", 34)).to eq( + { + "relatedIdentifier" => "10.1016/j.epsl.2011.11.037", + "relatedIdentifierType" => "DOI", + "relationType" => "Collects", + "resourceTypeGeneral" => "Other", + } + ) + expect(json.dig("data", "attributes", "relatedIdentifiers", 35)).to eq( + { + "relatedIdentifier" => "10.1016/j.epsl.2011.11.037", + "relatedIdentifierType" => "DOI", + "relationType" => "IsCollectedBy", + "resourceTypeGeneral" => "Other" + } + ) + + doc = Nokogiri::XML(Base64.decode64(json.dig("data", "attributes", "xml")), nil, "UTF-8", &:noblanks) + expect(doc.at_css("publisher").content).to eq("Example Publisher") + expect(doc.at_css("publisher")["publisherIdentifier"]).to eq("https://ror.org/04z8jg394") + expect(doc.at_css("publisher")["publisherIdentifierScheme"]).to eq("ROR") + expect(doc.at_css("publisher")["schemeURI"]).to eq("https://ror.org/") + expect(doc.at_css("publisher")["xml:lang"]).to eq("en") + + expect(Doi.where(doi: "10.14454/10703").first.publisher).to eq( + { + "name" => "Example Publisher", + "publisherIdentifier" => "https://ror.org/04z8jg394", + "publisherIdentifierScheme" => "ROR", + "schemeUri" => "https://ror.org/", + "lang" => "en", + } + ) + end + + it "creates a Doi with publisher param set to true" do + post "/dois?publisher=true", valid_attributes, headers + + expect(last_response.status).to eq(201) + expect(json.dig("data", "attributes", "doi")).to eq(doi) + expect(json.dig("data", "attributes", "schemaVersion")).to eq("http://datacite.org/schema/kernel-4") + expect(json.dig("data", "attributes", "state")).to eq("findable") + expect(json.dig("data", "attributes", "publisher")).to eq( + { + "name" => "Example Publisher", + "publisherIdentifier" => "https://ror.org/04z8jg394", + "publisherIdentifierScheme" => "ROR", + "schemeUri" => "https://ror.org/", + "lang" => "en", + } + ) + end + end + + context "when the request is valid with publisher as a hash" do + let(:valid_attributes) do + { + "data" => { + "type" => "dois", + "attributes" => { + "doi" => "10.14454/10703", + "url" => "http://www.bl.uk/pdf/patspec.pdf", + "types" => { "resourceTypeGeneral" => "Text" }, + "titles" => [{ "title" => "Eating your own Dog Food" }], + "publisher" => { + "name" => "DataCite", + "publisherIdentifier" => "https://ror.org/04wxnsj81", + "publisherIdentifierScheme" => "ROR", + "schemeUri" => "https://ror.org/", + "lang" => "en", + }, + "publicationYear" => 2016, + "creators" => [{ "familyName" => "Fenner", "givenName" => "Martin", "nameIdentifiers" => [{ "nameIdentifier" => "https://orcid.org/0000-0003-1419-2405", "nameIdentifierScheme" => "ORCID", "schemeUri" => "https://orcid.org" }], "name" => "Fenner, Martin", "nameType" => "Personal" }], + "event" => "publish", + }, + }, + } + end + + it "creates a Doi with publisher param not set" do + post "/dois", valid_attributes, headers + + expect(last_response.status).to eq(201) + expect(json.dig("data", "attributes", "url")).to eq("http://www.bl.uk/pdf/patspec.pdf") + expect(json.dig("data", "attributes", "doi")).to eq("10.14454/10703") + expect(json.dig("data", "attributes", "titles")).to eq([{ "title" => "Eating your own Dog Food" }]) + expect(json.dig("data", "attributes", "creators")).to eq([{ "affiliation" => [], "familyName" => "Fenner", "givenName" => "Martin", "nameIdentifiers" => [{ "nameIdentifier" => "https://orcid.org/0000-0003-1419-2405", "nameIdentifierScheme" => "ORCID", "schemeUri" => "https://orcid.org" }], "name" => "Fenner, Martin", "nameType" => "Personal" }]) + expect(json.dig("data", "attributes", "publisher")).to eq("DataCite") + expect(json.dig("data", "attributes", "publicationYear")).to eq(2016) + expect(json.dig("data", "attributes", "state")).to eq("findable") + + expect(Doi.where(doi: "10.14454/10703").first.publisher).to eq( + { + "name" => "DataCite", + "publisherIdentifier" => "https://ror.org/04wxnsj81", + "publisherIdentifierScheme" => "ROR", + "schemeUri" => "https://ror.org/", + "lang" => "en", + } + ) + end + + it "creates a Doi with publisher param set to true" do + post "/dois?publisher=true", valid_attributes, headers + + expect(last_response.status).to eq(201) + expect(json.dig("data", "attributes", "url")).to eq("http://www.bl.uk/pdf/patspec.pdf") + expect(json.dig("data", "attributes", "doi")).to eq("10.14454/10703") + expect(json.dig("data", "attributes", "titles")).to eq([{ "title" => "Eating your own Dog Food" }]) + expect(json.dig("data", "attributes", "creators")).to eq([{ "affiliation" => [], "familyName" => "Fenner", "givenName" => "Martin", "nameIdentifiers" => [{ "nameIdentifier" => "https://orcid.org/0000-0003-1419-2405", "nameIdentifierScheme" => "ORCID", "schemeUri" => "https://orcid.org" }], "name" => "Fenner, Martin", "nameType" => "Personal" }]) + expect(json.dig("data", "attributes", "publisher")).to eq( + { + "name" => "DataCite", + "publisherIdentifier" => "https://ror.org/04wxnsj81", + "publisherIdentifierScheme" => "ROR", + "schemeUri" => "https://ror.org/", + "lang" => "en", + } + ) + expect(json.dig("data", "attributes", "publicationYear")).to eq(2016) + expect(json.dig("data", "attributes", "state")).to eq("findable") + end + end + context "when the request uses namespaced xml" do let(:xml) { Base64.strict_encode64(file_fixture("ns0.xml").read) } let(:valid_attributes) do @@ -4048,6 +4279,175 @@ end end + describe "PUT /dois/:id" do + context "update publisher" do + let(:doi) { create(:doi, doi: "10.14454/10703", publisher: nil, client: client) } + let(:xml) { Base64.strict_encode64(file_fixture("datacite-example-full-v4.5.xml").read) } + + let(:publisher_as_string_attributes) do + { + "data" => { + "type" => "dois", + "attributes" => { + "publisher" => "DataCite", + "event" => "publish", + } + } + } + end + + let(:publisher_as_obj_attributes) do + { + "data" => { + "type" => "dois", + "attributes" => { + "publisher" => { + "name" => "DataCite", + "publisherIdentifier" => "https://ror.org/04wxnsj81", + "publisherIdentifierScheme" => "ROR", + "schemeUri" => "https://ror.org/", + "lang" => "en", + }, + "event" => "publish", + } + } + } + end + + let(:publisher_obj_in_xml) do + { + "data" => { + "type" => "dois", + "attributes" => { + "xml" => xml, + "event" => "publish", + }, + }, + } + end + + it "with publisher as string" do + put "/dois/#{doi.doi}", publisher_as_string_attributes, headers + + expect(last_response.status).to eq(200) + expect(json.dig("data", "attributes", "doi")).to eq(doi.doi) + expect(json.dig("data", "attributes", "schemaVersion")).to eq("http://datacite.org/schema/kernel-4") + expect(json.dig("data", "attributes", "state")).to eq("findable") + expect(json.dig("data", "attributes", "publisher")).to eq("DataCite") + + expect(Doi.where(doi: doi.doi).first.publisher).to eq( + { + "name" => "DataCite", + } + ) + end + + it "with publisher as string with publisher param set to true" do + put "/dois/#{doi.doi}?publisher=true", publisher_as_string_attributes, headers + + expect(last_response.status).to eq(200) + expect(json.dig("data", "attributes", "doi")).to eq(doi.doi) + expect(json.dig("data", "attributes", "schemaVersion")).to eq("http://datacite.org/schema/kernel-4") + expect(json.dig("data", "attributes", "state")).to eq("findable") + expect(json.dig("data", "attributes", "publisher")).to eq( + { + "name" => "DataCite", + } + ) + end + + it "with publisher as object" do + put "/dois/#{doi.doi}", publisher_as_obj_attributes, headers + + expect(last_response.status).to eq(200) + expect(json.dig("data", "attributes", "doi")).to eq(doi.doi) + expect(json.dig("data", "attributes", "schemaVersion")).to eq("http://datacite.org/schema/kernel-4") + expect(json.dig("data", "attributes", "state")).to eq("findable") + expect(json.dig("data", "attributes", "publisher")).to eq("DataCite") + + doc = Nokogiri::XML(Base64.decode64(json.dig("data", "attributes", "xml")), nil, "UTF-8", &:noblanks) + expect(doc.at_css("publisher").content).to eq("DataCite") + expect(doc.at_css("publisher")["publisherIdentifier"]).to eq("https://ror.org/04wxnsj81") + expect(doc.at_css("publisher")["publisherIdentifierScheme"]).to eq("ROR") + expect(doc.at_css("publisher")["schemeURI"]).to eq("https://ror.org/") + expect(doc.at_css("publisher")["xml:lang"]).to eq("en") + + expect(Doi.where(doi: doi.doi).first.publisher).to eq( + { + "name" => "DataCite", + "publisherIdentifier" => "https://ror.org/04wxnsj81", + "publisherIdentifierScheme" => "ROR", + "schemeUri" => "https://ror.org/", + "lang" => "en", + } + ) + end + + it "with publisher as object with publisher param set to true" do + put "/dois/#{doi.doi}?publisher=true", publisher_as_obj_attributes, headers + + expect(last_response.status).to eq(200) + expect(json.dig("data", "attributes", "doi")).to eq(doi.doi) + expect(json.dig("data", "attributes", "schemaVersion")).to eq("http://datacite.org/schema/kernel-4") + expect(json.dig("data", "attributes", "state")).to eq("findable") + expect(json.dig("data", "attributes", "publisher")).to eq( + { + "name" => "DataCite", + "publisherIdentifier" => "https://ror.org/04wxnsj81", + "publisherIdentifierScheme" => "ROR", + "schemeUri" => "https://ror.org/", + "lang" => "en", + } + ) + end + + it "with publisher obj in xml" do + put "/dois/#{doi.doi}", publisher_obj_in_xml, headers + + expect(last_response.status).to eq(200) + expect(json.dig("data", "attributes", "doi")).to eq(doi.doi) + expect(json.dig("data", "attributes", "schemaVersion")).to eq("http://datacite.org/schema/kernel-4") + expect(json.dig("data", "attributes", "state")).to eq("findable") + expect(json.dig("data", "attributes", "publisher")).to eq("Example Publisher") + + doc = Nokogiri::XML(Base64.decode64(json.dig("data", "attributes", "xml")), nil, "UTF-8", &:noblanks) + expect(doc.at_css("publisher").content).to eq("Example Publisher") + expect(doc.at_css("publisher")["publisherIdentifier"]).to eq("https://ror.org/04z8jg394") + expect(doc.at_css("publisher")["publisherIdentifierScheme"]).to eq("ROR") + expect(doc.at_css("publisher")["schemeURI"]).to eq("https://ror.org/") + expect(doc.at_css("publisher")["xml:lang"]).to eq("en") + + expect(Doi.where(doi: "10.14454/10703").first.publisher).to eq( + { + "name" => "Example Publisher", + "publisherIdentifier" => "https://ror.org/04z8jg394", + "publisherIdentifierScheme" => "ROR", + "schemeUri" => "https://ror.org/", + "lang" => "en", + } + ) + end + + it "with publisher obj in xml with publisher param set to true" do + put "/dois/#{doi.doi}?publisher=true", publisher_obj_in_xml, headers + + expect(last_response.status).to eq(200) + expect(json.dig("data", "attributes", "doi")).to eq(doi.doi) + expect(json.dig("data", "attributes", "schemaVersion")).to eq("http://datacite.org/schema/kernel-4") + expect(json.dig("data", "attributes", "state")).to eq("findable") + expect(json.dig("data", "attributes", "publisher")).to eq( + { + "name" => "Example Publisher", + "publisherIdentifier" => "https://ror.org/04z8jg394", + "publisherIdentifierScheme" => "ROR", + "schemeUri" => "https://ror.org/", + "lang" => "en", + } + ) + end + end + end + describe "DELETE /dois/:id" do let(:doi) { create(:doi, client: client, aasm_state: "draft") } @@ -4368,7 +4768,15 @@ expect(last_response.status).to eq(200) data = Maremma.from_xml(last_response.body).to_h.fetch("resource", {}) expect(data.dig("xmlns")).to eq("http://datacite.org/schema/kernel-4") - expect(data.dig("publisher")).to eq("Dryad Digital Repository") + expect(data.dig("publisher")).to eq( + { + "__content__" => "Dryad Digital Repository", + "publisherIdentifier" => "https://ror.org/00x6h5n95", + "publisherIdentifierScheme" => "ROR", + "schemeURI" => "https://ror.org/", + "xml:lang" => "en" + } + ) expect(data.dig("titles", "title")).to eq("Data from: A new malaria agent in African hominids.") end end @@ -4380,7 +4788,15 @@ expect(last_response.status).to eq(200) data = Maremma.from_xml(last_response.body).to_h.fetch("resource", {}) expect(data.dig("xmlns")).to eq("http://datacite.org/schema/kernel-4") - expect(data.dig("publisher")).to eq("Dryad Digital Repository") + expect(data.dig("publisher")).to eq( + { + "__content__" => "Dryad Digital Repository", + "publisherIdentifier" => "https://ror.org/00x6h5n95", + "publisherIdentifierScheme" => "ROR", + "schemeURI" => "https://ror.org/", + "xml:lang" => "en" + } + ) expect(data.dig("titles", "title")).to eq("Data from: A new malaria agent in African hominids.") end end diff --git a/spec/requests/index_spec.rb b/spec/requests/index_spec.rb index e960d0a77..a3679beae 100644 --- a/spec/requests/index_spec.rb +++ b/spec/requests/index_spec.rb @@ -47,7 +47,15 @@ expect(last_response.status).to eq(200) data = Maremma.from_xml(last_response.body).to_h.fetch("resource", {}) expect(data.dig("xmlns")).to eq("http://datacite.org/schema/kernel-4") - expect(data.dig("publisher")).to eq("Dryad Digital Repository") + expect(data.dig("publisher")).to eq( + { + "__content__" => "Dryad Digital Repository", + "publisherIdentifier" => "https://ror.org/00x6h5n95", + "publisherIdentifierScheme" => "ROR", + "schemeURI" => "https://ror.org/", + "xml:lang" => "en" + } + ) expect(data.dig("titles", "title")).to eq( "Data from: A new malaria agent in African hominids.", ) @@ -61,7 +69,15 @@ expect(last_response.status).to eq(200) data = Maremma.from_xml(last_response.body).to_h.fetch("resource", {}) expect(data.dig("xmlns")).to eq("http://datacite.org/schema/kernel-4") - expect(data.dig("publisher")).to eq("Dryad Digital Repository") + expect(data.dig("publisher")).to eq( + { + "__content__" => "Dryad Digital Repository", + "publisherIdentifier" => "https://ror.org/00x6h5n95", + "publisherIdentifierScheme" => "ROR", + "schemeURI" => "https://ror.org/", + "xml:lang" => "en" + } + ) expect(data.dig("titles", "title")).to eq( "Data from: A new malaria agent in African hominids.", )