Skip to content

Instantly share code, notes, and snippets.

@mankind
Last active June 29, 2020 14:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mankind/4e35946737496feb5d3ee25b803c0864 to your computer and use it in GitHub Desktop.
Save mankind/4e35946737496feb5d3ee25b803c0864 to your computer and use it in GitHub Desktop.
auto-populate forms using datacite and crossref api
module Ubiquity
class CrossrefResponse
attr_reader :error, :attributes
def initialize(response_hash = nil)
@error = error
@attributes = response_hash['message']
end
def title
attributes['title']
end
def abstract
# For removing the Jat tags inside the abstract
ActionView::Base.full_sanitizer.sanitize attributes['abstract']
end
def version
attributes['message-version']
end
def date_published_year
date_hash = attributes['published-online'].presence || attributes['published-print']
return date_hash['date-parts'].first[0] if date_hash
end
def date_published_month
date_hash = attributes['published-online'].presence || attributes['published-print']
return date_hash['date-parts'].first[1] if date_hash
end
def license
return nil if attributes['license'].blank?
url_array = fetch_url_from_response.split('/')
url_collection = Hyrax::LicenseService.new.select_active_options.map(&:last)
url_array.pop if url_array.last == 'legalcode'
url_array.shift(2) # Removing the http, https and // part in the url
regex_url_str = "(?:http|https)://" + url_array.map { |ele| "(#{ele})" }.join('/')
regex_url_exp = Regexp.new regex_url_str
url_collection.select { |e| e.match regex_url_exp }.first
end
def date_published_day
date_hash = attributes['published-online'].presence || attributes['published-print']
return date_hash['date-parts'].first[2] if date_hash
end
def issn
return nil if attributes['issn-type'].blank?
print_value = attributes['issn-type'].detect { |h| h['type'] == 'print' }
return print_value['value'] if print_value
end
def eissn
return nil if attributes['issn-type'].blank?
print_value = attributes['issn-type'].detect { |h| h['type'] == 'electronic' }
return print_value['value'] if print_value
end
def isbn
return nil if attributes['isbn-type'].blank?
print_value = attributes['isbn-type'].detect { |h| h['type'] == 'print' } || attributes['isbn-type'].detect { |h| h['type'] == 'electronic' }
return print_value['value'] if print_value['value']
attributes['isbn-type'].first['value']
end
def doi
attributes['DOI']
end
def volume
attributes['volume']
end
def pagination
attributes['page']
end
def issue
attributes['issue']
end
def journal_title
attributes['container-title'].first if attributes['container-title'].present?
end
def keyword
attributes['subject']
end
def publisher
attributes['publisher']
end
def official_url
attributes['URL']
end
#retuns an array of hash eg
# [{"DOI"=>"10.13039/501100000664", "name"=>"Health Technology Assessment Programme", "doi-asserted-by"=>"publisher", "award"=>["HTA 06/301/233", "HTA 09/127/53", "HTA 10/34/01", "HTA 96/20/06, HTA 96/20/99"]}]
#
#def funder
#attributes[['funder'].]
#end
def creator
creator_group = attributes.dig('author') || attributes.dig('editor')
if creator_group.present?
extract_creators(creator_group)
=begin
if creator_group.first.keys && ['given', 'family', 'ORCID'].any?
creator_with_seperated_names(creator_group)
else
creator_without_seperated_names(creator_group)
end
=end
end
end
def extract_creators(creator_data)
new_creator_group = []
creator_data.each_with_index do |hash, index|
if (hash.keys & ['given', 'family', 'ORCID']).any?
record = creator_with_seperated_names(hash, index)
else
record = creator_without_seperated_names(hash, index)
end
new_creator_group << record
end
new_creator_group
end
def creator_with_seperated_names(hash, index)
#def creator_with_seperated_names(data)
#new_creator_group = []
#data.each_with_index do |hash, index|
hash = {
creator_orcid: hash.try(:fetch, 'ORCID', '').split('/').last,
creator_given_name: hash["given"],
creator_family_name: hash["family"],
creator_name_type: 'Personal',
creator_position: index
}
#new_creator_group << hash
#end
#new_creator_group
end
def creator_without_seperated_names(hash, index)
#def creator_without_seperated_names(data)
#data.each_with_index do |hash, index|
hash = {
#creator_orcid: hash.try(:fetch, 'ORCID', '').split('/').last,
creator_organization_name: hash["name"],
creator_name_type: 'Organisational',
creator_position: index
}
#new_creator_group << hash
#end
#new_creator_group
end
def fetch_url_from_response
vor_version_license = attributes['license'].detect { |h| h['content-version'] == 'vor' }
return vor_version_license['URL'] if vor_version_license.present?
max_time_stamp_license = attributes['license'].max_by { |h| h.try(:fetch, 'date-parts', '')['time-stamp'].to_f }
return max_time_stamp_license['URL'] if max_time_stamp_license.present?
attributes['license'].first['URL']
end
# creator_group: creator, in front of doi
# issn: issn,
def data
if error.present?
{ 'error' => error }
else
{
title: title, published_year: date_published_year ,
published_month: date_published_month, published_day: date_published_day,
issn: issn, eissn: eissn, journal_title: journal_title,
abstract: abstract, version: version, isbn: isbn,
creator_group: creator, doi: doi, keyword: keyword, license: license,
publisher: publisher, volume: volume, pagination: pagination, issue: issue,
official_url: official_url
}
end
end
end
end
$(document).on("turbolinks:load", function(event){
return $("body").on("submit", ".get-datacite-doi-metadata-select", function(event){
var dataciteUrl = $(".ubiquity-datacite-value").val();
$(".ubiquity-fields-populated").hide()
$(".ubiquity-fields-populated-error").hide()
event.preventDefault();
fetchDataciteData(dataciteUrl);
$("#get-datacite-doi-metadata").modal('hide')
});
});
function fetchDataciteData(url) {
var host = window.document.location.host;
var protocol = window.document.location.protocol;
var fullHost = protocol + '//' + host + '/available_ubiquity_titles/call_datasite';
var field_array = [];
$.ajax({
url: fullHost,
type: "POST",
data: {"url": url},
success: function(result){
if (result.data.error === undefined) {
if($('.ubiquity-title').length != 0 && result.data.title != null) {
$(".ubiquity-title").val(result.data.title)
field_array.push('Title')
}
if ($('.ubiquity-abstract').length != 0 && result.data.abstract != null) {
field_array.push('Abstract')
$('.ubiquity-abstract').val(result.data.abstract)
}
if($('.ubiquity-doi').length != 0 && result.data.doi != null) {
field_array.push('DOI')
$('.ubiquity-doi').val(result.data.doi)
}
if($('.ubiquity-official-link').length != 0 && result.data.official_url != null) {
field_array.push('Official URL')
$('.ubiquity-official-link').val(result.data.official_url)
}
//populate dropdown
if($('.ubiquity-date-published-year').length != 0 && result.data.published_year != null) {
field_array.push('Published Year')
$('.ubiquity-date-published-year').val(result.data.published_year);
}
if($('.ubiquity-date-published-month').length != 0 && result.data.published_month != null) {
field_array.push('Published Month')
$('.ubiquity-date-published-month').val(result.data.published_month);
}
if($('.ubiquity-date-published-day').length != 0 && result.data.published_day != null) {
field_array.push('Published Day')
$('.ubiquity-date-published-day').val(result.data.published_day);
}
if($('.ubiquity-volume').length != 0 && result.data.volume != null) {
field_array.push('Volume')
$('.ubiquity-volume').val(result.data.volume);
}
if($('.ubiquity-issue').length != 0 && result.data.issue != null) {
field_array.push('Issue')
$('.ubiquity-issue').val(result.data.issue);
}
if($('.ubiquity-pagination').length != 0 && result.data.pagination != null) {
field_array.push('Pagination')
$('.ubiquity-pagination').val(result.data.pagination);
}
if($('.ubiquity-license').length != 0 && result.data.license != null && (result.data.license && result.data.license.active) == undefined) {
field_array.push('Licence')
$('.ubiquity-license').val(result.data.license)
} else if ($('.ubiquity-license').length != 0 && result.data.license && result.data.license.active == false && result.data.license.license != null ) {
field_array.push('Licence')
$(".ubiquity-license").append(new Option(result.data.license.label, result.data.license.license))
$('.ubiquity-license').val(result.data.license.license)
}
if($('.ubiquity-funder').length != 0 && result.data.funder != null) {
field_array.push('Funder')
$('.ubiquity-funder').val(result.data.funder);
}
if($('.ubiquity-issn').length != 0 && result.data.issn != null) {
field_array.push('ISSN')
$('.ubiquity-issn').val(result.data.issn);
}
if($('.ubiquity-journal-title').length != 0 && result.data.journal_title != null) {
field_array.push('Journal Title')
$('.ubiquity-journal-title').val(result.data.journal_title);
}
if($('.ubiquity-eissn').length != 0 && result.data.eissn != null) {
field_array.push('eISSN')
$('.ubiquity-eissn').val(result.data.eissn);
}
if($('.ubiquity-isbn').length != 0 && result.data.isbn != null) {
field_array.push('ISBN')
$('.ubiquity-isbn').val(result.data.isbn);
}
if($('.ubiquity-publisher').length != 0 && result.data.publisher != null) {
field_array.push('Publisher')
$('.ubiquity-publisher').val(result.data.publisher);
}
if ($(".ubiquity-meta-related-identifier") != 0 && result.data.related_identifier_group != null) {
field_array.push('Related Identifier')
populateRelatedIdentifierValues(result.data.related_identifier_group)
}
if ($(".ubiquity-meta-creator").length != 0 && result.data.creator_group != null) {
field_array.push('Creator')
populateCreatorValues(result.data.creator_group);
}
if ($(".ubiquity-meta-contributor").length != 0 && result.data.contributor_group != null) {
field_array.push('Contributor')
populateContributorValues(result.data.contributor_group);
}
if ($(".ubiquity-keyword").length != 0 && result.data.keyword != null) {
field_array.push('Keyword')
populateKeyword(result.data.keyword)
}
if ($(".ubiquity-version-number").length != 0 && result.data.version != null) {
field_array.push('Version')
$(".ubiquity-version-number").val(result.data.version)
}
//IE11 will not show the ,message when .val() is used hence .html()
var message = "The following fields were auto-populated " + field_array.slice(0, field_array.length - 1).join(', ') + ", and " + field_array.slice(-1);
$(".ubiquity-fields-populated").html(message)
$(".ubiquity-fields-populated").show()
} else {
$(".ubiquity-fields-populated-error").html(result.data.error)
$(".ubiquity-fields-populated-error").show()
}
}
}) //closes $.ajax
}
function populateRelatedIdentifierValues(relatedArray){
$.each(relatedArray, function(key, value){
addValues(key, value);
})
}
function populateKeyword(keywordArray){
$.each(keywordArray, function(key, value){
addKeywordValues(key, value);
})
}
function addKeywordValues(key, value){
if (key == 0) {
$(".ubiquity-keyword:last").val(value)
}
else{
var parent_li = $(".ubiquity-keyword:last").parent();
var clonedParent = parent_li.clone();
var parent_ul = parent_li.parent();
parent_ul.append(clonedParent);
$(".ubiquity-keyword:last").val(value);
}
}
function addValues(key, value) {
if (key === 0) {
var div = $(".ubiquity-meta-related-identifier");
div.children(".related_identifier").val(value.related_identifier)
$('.related_identifier_type').val(value.related_identifier_type).change()
div.children(".related_identifier_relation:last").val(value.relation_type).change()
}else {
var div = $(".ubiquity-meta-related-identifier:last")
var cloned = div.clone();
cloned.find('input').val('');
cloned.find('option').attr('selected', false);
div.after(cloned)
cloned.children(".related_identifier:last").val(value.related_identifier)
$('.related_identifier_type').val(value.related_identifier_type).change()
cloned.children(".related_identifier_relation:last").val(value.relation_type).change()
}
}
function populateCreatorValues(creatorArray){
$.each(creatorArray, function(key, value){
//if (creatorArray[0].creator_name_type == "Organisational") {
if (value && value.creator_name_type == "Organisational") {
addOrganizationalValues('creator', key, value);
} else if (value && value.creator_name_type == "Personal") {
addPersonalValues('creator', key, value);
}
})
}
function populateContributorValues(contributorArray){
$.each(contributorArray, function(key, value){
if (value && value.creator_name_type == "Personal") {
addPersonalValues('contributor', key, value);
} else if (value && value.creator_name_type == "Organisational") {
addOrganizationalValues('contributor', key, value);
}
})
}
function addPersonalValues(fieldName, key, value) {
var familyName = '.' + fieldName + '_family_name:last'
var givenName = '.' + fieldName + '_given_name:last'
var givenName2 = '.' + fieldName + '_given_name'
var orcid = '.' + fieldName + '_orcid:last'
var isni = '.ubiquity_' + fieldName + '_isni:last'
var position = '.' + fieldName + '_position:last'
var nameType = '.' + 'ubiquity_' + fieldName + '_name_type:last'
if (key === 0) {
var newParent = '.ubiquity-meta-' + fieldName
var parent = $(newParent);
var div = parent.children(".ubiquity_personal_fields:last")
div.children(familyName).val(value[fieldName + '_family_name'])
div.children(givenName2).val(value[fieldName + '_given_name'])
parent.children(isni).val(value[fieldName + '_isni'])
div.children(orcid).val(getValidOrcid(value[fieldName + '_orcid']))
div.children(position).val(value[fieldName + '_position'])
parent.children(nameType).val('Personal').change()
}else {
var newParent = '.ubiquity-meta-' + fieldName + ':last'
var parent = $(newParent);
var parentClone = parent.clone();
var div = parentClone.children(".ubiquity_personal_fields:last")
parentClone.find('input').val('');
parentClone.find('option').attr('selected', false);
parent.after(parentClone)
parentClone.find(familyName).val(value[fieldName + '_family_name'])
parentClone.find(givenName).val(value[fieldName + '_given_name'])
parentClone.children(isni).val(value[fieldName + '_isni'])
div.children(orcid).val(getValidOrcid(value[fieldName + '_orcid']))
parentClone.find(position).val(value[fieldName + '_position'])
parentClone.find(nameType).val('Personal').change()
}
}
function addOrganizationalValues(fieldName, key, value) {
var name = '.ubiquity_' + fieldName + '_organization_name:last'
var name2 = '.ubiquity_' + fieldName + '_organization_name'
var isni = '.ubiquity_' + fieldName + '_isni:last'
var position = '.' + fieldName + '_position:last'
var nameType = '.' + 'ubiquity_' + fieldName + '_name_type:last'
if (key === 0) {
var newParent = '.ubiquity-meta-' + fieldName
var parent = $(newParent);
var div = parent.children(".ubiquity_organization_fields:last")
div.children(name).val(value[fieldName + '_organization_name'])
parent.children(isni).val(value[fieldName + '_isni'])
div.children(position).val(value[fieldName + '_position'])
parent.children(nameType).val('Organisational').change()
}else {
var newParent = '.ubiquity-meta-' + fieldName + ':last'
var parent = $(newParent);
var parentClone = parent.clone();
var div = parentClone.children(".ubiquity_organization_fields:last")
parentClone.find('input').val('');
parentClone.find('option').attr('selected', false);
parent.after(parentClone)
parentClone.find(name).val(value[fieldName + '_organization_name'])
parentClone.children(isni).val(value[fieldName + '_isni'])
parentClone.find(position).val(value[fieldName + '_position'])
parentClone.find(nameType).val('Organisational').change()
}
}
function getValidOrcid(orcidPath) {
if (orcidPath != null) {
var orcidArray = orcidPath.split("/")
var validOrcid = orcidArray.slice(-1)[0]
}
return validOrcid
}
module Ubiquity
class DataciteClient
attr_accessor :path
def initialize(url)
#sets the value of the path ,method
decoded_url = CGI.unescape(url)
parse_url(decoded_url)
end
def fetch_record
result = fetch_record_from_crossref
if result.class == HTTParty::Response
response_hash = result.parsed_response
return response_object_from_crossref(response_hash) if response_hash.class == Hash && response_hash['message'].class == Hash
end
result = fetch_record_from_datacite
if result.class == HTTParty::Response
response_hash = result.parsed_response
response_object_from_datacite(response_hash, result)
else
Ubiquity::DataciteResponse.new(error: error_message, result: result)
end
end
def fetch_record_from_crossref
handle_client do
HTTParty.get("https://api.crossref.org/works/#{path}")
end
end
def fetch_record_from_datacite
handle_datacite_client do
puts "pata #{path}"
HTTParty.get("https://api.datacite.org/dois/#{path}")
end
end
private
def response_object_from_datacite(response_hash, result)
if response_hash.present? && response_hash.class == Hash && response_hash['data'].class == Hash
Ubiquity::DataciteResponse.new(response_hash: response_hash, result: result)
else
puts "Successful DataciteClient api call but HTTParty parsed_response returned a string instead of hash, so change url"
Ubiquity::DataciteResponse.new(error: error_message, result: result)
end
end
def response_object_from_crossref(response_hash)
Ubiquity::CrossrefResponse.new(response_hash)
end
def parse_url(url)
url = url.strip
handle_client do
uri = Addressable::URI.convert_path(url)
puts "debo #{uri}"
if (uri.scheme.present? && uri.host.present?)
path_name = uri.path
puts "insidi-1 #{path_name}"
use_path(path_name)
elsif (uri.scheme.present? == false && uri.host.present? == false && uri.path.present?)
puts "insidoelse #{uri.path}"
use_path(uri.path)
end
end
end
def use_path(path_name)
puts "uri #{path_name}"
split_path = path_name.split('/').reject(&:empty?)
if (split_path.length == 3 && split_path.first == 'works') || ( split_path.length == 4 && split_path.first == 'works')
puts "lagos"
#changes "works/10.5438/0012" to "/works/10.5438/0012"
path_name = path_name.prepend('/') if path_name.slice(0) != "/"
@path = path_name
elsif split_path.length == 4 && split_path.first == 'api.datacite.org'
puts "abuja"
#data here is ["api.datacite.org", "works", "10.5438", "0012"]
#shift removes the first element
split_path.shift
#we get back "works/#{path_name}"
url_path =split_path.join('/')
#we get back "/works/#{path_name}"
new_url_path = url_path.prepend('/')
@path = new_url_path
#when split_path returns ["10.7488", "ds", "2109"]
#we get the first two elements that is "10" with
#split_path.first.slice(0..1)
elsif (split_path.length == 2 && (not split_path.include? 'works')) || (split_path.length == 3 && split_path.first.slice(0..1) == '10')
path_name = path_name.prepend('/') if path_name.slice(0) != "/"
puts "no-api #{path_name}"
@path = path_name
end
end
def handle_client
begin
yield
rescue URI::InvalidURIError, HTTParty::Error, Net::HTTPNotFound, NoMethodError, Net::OpenTimeout, StandardError => e
puts "DataciteClient error #{e.inspect}"
end
end
def handle_datacite_client
begin
yield
rescue URI::InvalidURIError, HTTParty::Error, Net::HTTPNotFound, NoMethodError, Net::OpenTimeout, StandardError => e
puts " This is from the datacitre client #{e.inspect}"
end
end
def error_message
"Sorry no data was fetched. Please ensure this is a valid DataCite DOI or URL eg 10.5438/0012 or https://doi.org/10.5438/0012 or
http://dx.doi.org/10.18154/RWTH-CONV-020567 or http://api.crossref.org/works/10.11647/OBP.0172. If you are sure it is valid please refresh the page and try again."
end
end
end
module Ubiquity
class DataciteResponse
attr_accessor :api_response, :error
attr_reader :raw_http_response, :attributes
def initialize(response_hash: nil, result: nil, error: nil)
@api_response = response_hash
@raw_http_response = result
@error = error
@attributes = response_hash['data']['attributes'] if !response_hash.nil? && response_hash.class == Hash
end
def title
if attributes['titles'].present?
attributes['titles'][0]['title']
end
end
def date_published_year
attributes['published']
end
def abstract
if attributes['descriptions'].present? && attributes['descriptions'][0]['description'].present?
ActionView::Base.full_sanitizer.sanitize attributes['descriptions'][0]['description']
end
end
def version
attributes.dig('version')
end
def funder
if attributes.dig('fundingReferences').present?
attributes.dig('fundingReferences').first["funderName"]
end
end
def license
if attributes.dig("rightsList").present?
url_array = attributes.dig("rightsList").last["rightsUri"].split('/')
url_active_collection = Hyrax::LicenseService.new.select_active_options.map(&:last)
url_all_collection = Hyrax::LicenseService.new.select_all_options.map(&:last)
url_inactive_collection = url_all_collection - url_active_collection
url_array.pop if url_array.last == 'legalcode'
url_array.shift(2) # Removing the http, https and // part in the url
regex_url_str = "(?:http|https)://" + url_array.map { |ele| "(#{ele})" }.join('/')
regex_url_exp = Regexp.new regex_url_str
license_result = url_active_collection.select { |e| e.match regex_url_exp }.first
return_license(license_result, url_inactive_collection, regex_url_exp)
end
end
def doi
attributes.dig('doi')
end
def official_url
identifiers_array = attributes.dig('identifiers')
result = identifiers_array.map do |hash|
hash['identifier'] if hash.has_value?('URL') || hash['identifier'] if hash.has_value?('DOI')
end
result.compact.first
end
def publisher
attributes.dig('publisher')
end
def creator
creator_group = attributes.dig('creators')
if creator_group.present?
extract_creators(creator_group)
end
end
def extract_creators(creator_data)
new_creator_group = []
creator_data.each_with_index do |hash, index|
if hash["nameType"] == "Personal"
record = json_with_personal_name_type(hash, index)
elsif hash["nameType"] == "Organizational"
record = json_with_organisation_name_type(hash, index)
end
new_creator_group << record
end
new_creator_group
end
def contributor
contributor_group = attributes.dig('contributors')
if contributor_group.present?
if contributor_group.first.keys.to_set.intersect? ["nameType", :nameType].to_set
json_with_personal_name_type('contributor', contributor_group)
else
json_with_organisation_name_type('contributor', contributor_group)
end
end
end
def related_identifier
related_group = attributes['relatedIdentifiers']
if related_group.present?
related_group.map do |hash|
{
"relation_type" => hash["relation-type-id"],
"related_identifier" => hash["related-identifier"],
"related_identifier_type" => 'DOI'
}
end
end
end
def data
if error.present?
{ 'error' => error }
else
{
'related_identifier_group': related_identifier,
"title": title, "published_year": date_published_year,
"abstract": abstract, "version": version,
"creator_group": creator, "license": license,
"doi": doi, "contributor_group": contributor,
"publisher": publisher, "official_url": official_url,
"funder": funder
}
end
end
private
def return_license(license_result, url_inactive_collection, regex_url_exp)
if license_result != nil
license_result
else
object = {}
label = attributes.dig("rightsList").last["rights"].split(':')[1]
license_result = url_inactive_collection.select { |e| e.match regex_url_exp }.first
object = {
"license": license_result,
"active": false,
"label": label
}
object
end
end
def json_with_personal_name_type(hash, index)
hash = {
"creator_given_name" => hash["givenName"],
"creator_family_name" => hash["familyName"],
"creator_orcid" => get_isni_from_nameIdentifiers(hash['nameIdentifiers']), #nameIdentifiers(hash),
"creator_isni" => get_isni_from_nameIdentifiers(hash['nameIdentifiers']),
"creator_name_type" => hash['nameType'],
"creator_position" => index
}
end
=begin
def nameIdentifiers(hash)
if hash["nameIdentifiers"].present?
orcid = hash["nameIdentifiers"][0]['nameIdentifier']
end
orcid
end
=end
def get_orcid_from_nameIdentifiers(array_of_identifiers)
if hash["nameIdentifiers"].present?
orcid = array_of_identifiers.map do |hash_idenifier|
if hash_idenifier["nameIdentifierScheme"] == "ORCID"
hash_idenifier['nameIdentifier']
end
end
end
orcid.first
end
def get_isni_from_nameIdentifiers(array_of_identifiers)
if array_of_identifiers.present?
identifier = array_of_identifiers.map do |hash_idenifier|
if hash_idenifier["nameIdentifierScheme"] == "ISNI"
hash_idenifier['nameIdentifier']
elsif hash_idenifier["nameIdentifierScheme"] == "ORCID"
hash_idenifier['nameIdentifier']
end
end
end
identifier.try(:first).presence
end
def json_with_organisation_name_type(hash, index)
remap_organization = {'Organization' => 'Organisation'}
hash = {
creator_isni: get_isni_from_nameIdentifiers(hash['nameIdentifiers']),
creator_organization_name: hash["name"],
creator_name_type: 'Organisational',
creator_position: index
}
end
end
end
module Ubiquity
class CrossrefResponse
attr_reader :error, :attributes
def initialize(response_hash = nil)
@error = error
@attributes = response_hash['message']
end
def title
attributes['title']
end
def abstract
# For removing the Jat tags inside the abstract
ActionView::Base.full_sanitizer.sanitize attributes['abstract']
end
def version
attributes['message-version']
end
def date_published_year
date_hash = attributes['published-online'].presence || attributes['published-print']
return date_hash['date-parts'].first[0] if date_hash
end
def date_published_month
date_hash = attributes['published-online'].presence || attributes['published-print']
return date_hash['date-parts'].first[1] if date_hash
end
def license
return nil if attributes['license'].blank?
url_array = fetch_url_from_response.split('/')
url_collection = Hyrax::LicenseService.new.select_active_options.map(&:last)
rurl_array.pop if url_array.last == 'legalcode'
url_array.shift(2) # Removing the http, https and // part in the url
regex_url_str = "(?:http|https)://" + url_array.map { |ele| "(#{ele})" }.join('/')
regex_url_exp = Regexp.new regex_url_str
url_collection.select { |e| e.match regex_url_exp }.first
end
def date_published_day
date_hash = attributes['published-online'].presence || attributes['published-print']
return date_hash['date-parts'].first[2] if date_hash
end
def issn
return nil if attributes['issn-type'].blank?
print_value = attributes['issn-type'].detect { |h| h['type'] == 'print' }
return print_value['value'] if print_value
end
def eissn
return nil if attributes['issn-type'].blank?
print_value = attributes['issn-type'].detect { |h| h['type'] == 'electronic' }
return print_value['value'] if print_value
end
def isbn
return nil if attributes['isbn-type'].blank?
print_value = attributes['isbn-type'].detect { |h| h['type'] == 'print' } || attributes['isbn-type'].detect { |h| h['type'] == 'electronic' }
return print_value['value'] if print_value['value']
attributes['isbn-type'].first['value']
end
def doi
attributes['DOI']
end
def volume
attributes['volume']
end
def pagination
attributes['page']
end
def issue
attributes['issue']
end
def journal_title
attributes['container-title'].first if attributes['container-title'].present?
end
def creator
creator_group = attributes.dig('author') || attributes.dig('editor')
if creator_group.present?
if creator_group.first.keys && ['given', 'family', 'ORCID'].any?
creator_with_seperated_names(creator_group)
else
creator_without_seperated_names(creator_group)
end
end
end
def keyword
attributes['subject']
end
def publisher
attributes['publisher']
end
def official_url
attributes['URL']
end
def creator_with_seperated_names(data)
new_creator_group = []
data.each_with_index do |hash, index|
hash = {
creator_orcid: hash.try(:fetch, 'ORCID', '').split('/').last,
creator_given_name: hash["given"],
creator_family_name: hash["family"],
creator_name_type: 'Personal',
creator_position: index
}
new_creator_group << hash
end
new_creator_group
end
url = def fetch_url_from_response
vor_version_license = attributes['license'].detect { |h| h['content-version'] == 'vor' }
return vor_version_license['URL'] if vor_version_license.present?
max_time_stamp_license = attributes['license'].max_by { |h| h.try(:fetch, 'date-parts', '')['time-stamp'].to_f }
return max_time_stamp_license['URL'] if max_time_stamp_license.present?
attributes['license'].first['URL']
end
def data
if error.present?
{ 'error' => error }
else
{
title: title, published_year: date_published_year,
published_month: date_published_month, published_day: date_published_day,
issn: issn, eissn: eissn, journal_title: journal_title,
abstract: abstract, version: version, isbn: isbn,
creator_group: creator, doi: doi, keyword: keyword, license: license,
publisher: publisher, volume: volume, pagination: pagination, issue: issue,
official_url: official_url
}
end
end
end
end
RSpec.describe Ubiquity::DataciteResponse do
include DataCiteCrossrefClientHelpers
let (:json_data) {File.read(Rails.root.join("spec/fixtures/json/datacite_v2.json")) }
let (:full_datacite_url) { 'https://dx.doi.org/10.15123%2FPUB.7627' }
let (:datacite_client_1) {Ubiquity::DataciteClient.new(full_datacite_url)}
let (:crossref_client_1) {Ubiquity::DataciteClient.new(full_datacite_url)}
before(:each) do
stub_request_datacite_client1(datacite_client_1, json_data)
stub_request_crossref_client1(crossref_client_1, json_data)
result = datacite_client_1.fetch_record
@response_hash = result.api_response
@response_object = described_class.new(response_hash: @response_hash, result: result)
@data_hash = @response_object.api_response["data"]["attributes"]
@json_object = JSON.parse(json_data)
end
context 'check values in response hash' do
describe '#title' do
it 'returns the property title' do
title_from_json_data = @json_object["data"]["attributes"]["title"]
title_from_response = @data_hash["title"]
expect(title_from_response).to eq title_from_json_data
end
end
describe '#date_published_year' do
it 'returns the property date_published_year' do
year_from_response = @response_object.date_published_year
year_from_json_data = @json_object["data"]["attributes"]["published"]
expect(year_from_response).to eq year_from_json_data
end
end
describe '#abstract' do
it 'returns the property description/abstract' do
description_from_response = @data_hash["description"]
description_from_json_data = @json_object["data"]["attributes"]["description"]
expect(description_from_response).to eq description_from_json_data
end
end
describe '#version' do
it 'returns the property version' do
version_from_response = @response_object.version
version_from_json_data = @json_object["data"]["attributes"].dig('version')
expect(version_from_response).to eq version_from_json_data
end
end
describe '#doi' do
it 'returns the property doi identifier' do
doi_from_response = @response_object.doi["doi"]
doi_from_json_data = @json_object["data"]["attributes"].dig('identifier')
expect(doi_from_response).to eq doi_from_json_data
end
end
describe '#funder' do
it 'returns the property funder' do
funder_from_response = @response_object.funder
funder_from_json_data = nil if @json_object["data"]["attributes"].dig('fundingReferences') == []
expect(funder_from_response).to eq nil
end
end
describe '#official_url' do
it 'returns the property official_url' do
official_url_from_response = @response_object.official_url
official_url_from_json_data = @json_object["data"]["attributes"]["identifiers"][0]["identifier"]
expect(official_url_from_response).to eq official_url_from_json_data
end
end
describe '#publisher' do
it 'returns the property publisher' do
official_url_from_response = @response_object.publisher
official_url_from_json_data = @json_object["data"]["attributes"]["publisher"]
expect(official_url_from_response).to eq official_url_from_json_data
end
end
describe '#creator' do
it 'returns the property creator' do
creator_name_from_response = @response_object.creator[0]["creator_given_name"]
creator_name_from_json_data = @json_object["data"]["attributes"].dig('creators')[0]['givenName']
creator_family_name_from_response = @response_object.creator[0]["creator_family_name"]
creator_family_name_from_json_data = @json_object["data"]["attributes"].dig('creators')[0]['familyName']
expect(creator_name_from_response).to eq creator_name_from_json_data
expect(creator_family_name_from_response).to eq creator_family_name_from_json_data
end
end
describe '#contributor' do
it 'returns the property contributor' do
contributor_name_from_response = @response_object.contributor
contributor_name_from_response = [] if contributor_name_from_response == nil
contributor_name_from_json_data = @json_object["data"]["attributes"]['contributors']
expect(contributor_name_from_response).to eq contributor_name_from_json_data
end
end
describe '#license' do
it 'returns the property license' do
license_from_response = @response_object.license[:license]
if license_from_response.present?
license_from_json_data = @json_object["data"]["attributes"]["rightsList"].last["rightsUri"]
else
license_from_json_data = nil
end
expect(license_from_response).to eq license_from_json_data
end
end
describe '#related_identifier' do
it 'returns the property related_identifier' do
identifier_from_response = @response_object.related_identifier
identifier_from_json_data = nil if @json_object["data"]["attributes"]['relatedIdentifiers'] == []
expect(identifier_from_response).to eq identifier_from_json_data
end
end
describe '#Instance of DataciteResponse' do
it 'returns an instance of DataciteResponse' do
expect(@response_object).to be_an_instance_of(Ubiquity::DataciteResponse)
end
end
end
end
module DataCiteCrossrefClientHelpers
def stub_request_datacite_client1(datacite_client_1, json_data)
stub_request(:get, "https://api.datacite.org/dois/#{datacite_client_1.path}").
with(headers: {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'User-Agent'=>'Ruby'}).
to_return(status: 200, body: json_data, headers: {'Content-Type'=>'application/json; charset=utf-8'})
end
def stub_request_datacite_client2(datacite_client_2, json_data)
stub_request(:get, "https://api.datacite.org/dois/#{datacite_client_2.path}").
with(headers: {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'User-Agent'=>'Ruby'}).
to_return(status: 200, body: json_data, headers: {'Content-Type'=>'application/json; charset=utf-8'})
end
def stub_request_crossref_client1(crossref_client_1, json_data)
stub_request(:get, "https://api.crossref.org/works/#{crossref_client_1.path}").
with(headers: {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'User-Agent'=>'Ruby'}).
to_return(status: 200, body: json_data, headers: {'Content-Type'=>'application/json; charset=utf-8'})
end
def stub_request_crossref_client2(crossref_client_2, json_data)
stub_request(:get, "https://api.crossref.org/works/#{crossref_client_2.path}").
with(headers: {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'User-Agent'=>'Ruby'}).
to_return(status: 200, body: json_data, headers: {'Content-Type'=>'application/json; charset=utf-8'})
end
end
RSpec.describe Ubiquity::DataciteClient do
include DataCiteCrossrefClientHelpers
let (:json_data) {File.read(Rails.root.join("spec/fixtures/json/datacite_v1.json")) }
let (:full_datacite_url) { 'https://dx.doi.org/10.15123%2FPUB.7627' }
let (:partial_datacite_url) { '10.15123%2FPUB.7627' }
let (:datacite_client_1) {described_class.new(full_datacite_url)}
let (:datacite_client_2) {described_class.new(partial_datacite_url)}
context 'initialize datacite client with an HTTP GET to /api.datacite.org' do
#fetch_record_from_datacite
describe '#path' do
it 'returns a path ' do
stub_request_datacite_client1(datacite_client_1, json_data)
expect(datacite_client_1.path).to eq "/10.15123/PUB.7627"
end
end
end
context 'fetch_record_from_datacite' do
describe '#fetch_record with full url' do
it 'returns a HTTParty::Response' do
stub_request_datacite_client1(datacite_client_1, json_data)
response_object = datacite_client_1.fetch_record_from_datacite
fetch_record_expectations(response_object, json_data)
end
end
describe '#fetch_record with url path' do
it 'returns a HTTParty::Response' do
stub_request_datacite_client2(datacite_client_2, json_data)
response_object = datacite_client_2.fetch_record_from_datacite
fetch_record_expectations(response_object, json_data)
end
end
end
private
def fetch_record_expectations(response_object, json_record)
expect(response_object.class).to eq HTTParty::Response
expect(response_object.success?).to eq true
expect(response_object.headers['content-type']).to eq "application/json; charset=utf-8"
expect(response_object.parsed_response).to eq JSON.parse(json_record)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment