Skip to content

Instantly share code, notes, and snippets.

@arfon
Last active July 3, 2018 00:18
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 arfon/372b9e8c8cbcba23d41407ef3e97b8fe to your computer and use it in GitHub Desktop.
Save arfon/372b9e8c8cbcba23d41407ef3e97b8fe to your computer and use it in GitHub Desktop.
Ruby class for validating ORCID formats and checksums
The MIT License (MIT)
Copyright (c) 2018 Arfon Smith
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
class String
def numeric?
Float(self) != nil rescue false
end
end
class OrcidValidator
attr_reader :orcid
def initialize(orcid)
@orcid = orcid.strip
end
# Returns true or false
def validate
check_structure
check_length
check_chars
if checksum_char == "X" || checksum_char == "x"
return checksum == 10
else
return checksum == checksum_char.to_i
end
end
def packed_orcid
orcid.gsub('-', '')
end
# Returns the last character of the string
def checksum_char
packed_orcid[-1]
end
def first_11
packed_orcid.chop
end
def check_structure
groups = orcid.split('-')
warn("ORCID looks malformed") unless groups.size == 4
end
def check_length
warn("ORCID looks to be the wrong length") unless packed_orcid.length == 16
end
def check_chars
first_11.each_char do |c|
warn("Invalid ORDIC digit (#{c})") unless c.numeric?
end
end
# https://support.orcid.org/knowledgebase/articles/116780-structure-of-the-orcid-identifier
def checksum
total = 0
first_11.each_char do |c|
total = (total + c.to_i) * 2
end
remainder = total % 11
result = (12 - remainder) % 11
return result
end
end
p OrcidValidator.new("0000-0002-3957-2474").validate
# true
p OrcidValidator.new("0000-0002-3957-247X").validate
# false
p OrcidValidator.new("0000-0002-3957-247").validate
# ORCID looks to be the wrong length
# false
p OrcidValidator.new("0000-0002-3957-24XX").validate
# Invalid ORDIC digit (X)
# false
p OrcidValidator.new("0000000239572474").validate
# ORCID looks malformed
# true
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment