module StdNum::ISBN
Validate, convert, and normalize ISBNs (10-digit or 13-digit)
Constants
- TEN_TO_THIRTEEN_PREFIX
- VALID_THIRTEEN_PREFIX
Public Class Methods
Return an array of the ISBN13 and ISBN10 (in that order) for the passed in value. You'll only get one value back if it's a 13-digit ISBN
that can't be converted to an ISBN10. @param [String] isbn The original ISBN
, in 10-character or 13-digit format @return [Array<String,String>, nil] Either the (one or two) normalized ISBNs, or nil if it can't be recognized.
@example Get the normalized values and index them (if valid) or original value (if not)
norms = StdNum::ISBN.allNormalizedValues(rawisbn) doc['isbn'] = norms ? norms : [rawisbn]
# File lib/library_stdnums.rb, line 180 def self.allNormalizedValues isbn isbn = reduce_to_basics isbn, [10,13] return [] unless isbn case isbn.size when 10 return [self.convert_to_13(isbn), isbn] when 13 return [isbn, self.convert_to_10(isbn)].compact end end
Does it even look like an ISBN
?
# File lib/library_stdnums.rb, line 71 def self.at_least_trying? isbn reduce_to_basics(isbn, [10,13]) ? true : false end
Compute check digits for 10 or 13-digit ISBNs. See algorithm at en.wikipedia.org/wiki/International_Standard_Book_Number @param [String] isbn The ISBN
(we'll try to clean it up if possible) @param [Boolean] preprocessed Set to true if the ISBN
has already been through reduce_to_basics @return [String,nil] the one-character checkdigit, or nil if it's not an ISBN
string
# File lib/library_stdnums.rb, line 81 def self.checkdigit isbn, preprocessed = false isbn = reduce_to_basics isbn, [10,13] unless preprocessed return nil unless isbn checkdigit = 0 if isbn.size == 10 digits = isbn[0..8].split(//).map {|i| i.to_i} (1..9).each do |i| checkdigit += digits[i-1] * i end checkdigit = checkdigit % 11 return 'X' if checkdigit == 10 return checkdigit.to_s else # size == 13 checkdigit = 0 digits = isbn[0..11].split(//).map {|i| i.to_i} 6.times do checkdigit += digits.shift checkdigit += digits.shift * 3 end check = 10 - (checkdigit % 10) check = 0 if check == 10 return check.to_s end end
Convert to 10 if it's 13 digits and the first three digits are 978. Pass through anything 10-digits, and return nil for everything else. @param [String] isbn The ISBN
(we'll try to clean it up if possible) @return [String] The converted 10-character ISBN
, nil if something looks wrong, or whatever was passed in if it already looked like a 10-digit ISBN
# File lib/library_stdnums.rb, line 157 def self.convert_to_10 isbn isbn = reduce_to_basics isbn, [10,13] # Already 10 digits? Just return return isbn if isbn.size == 10 # Can't be converted to ISBN-10? Bail return nil unless isbn[0..2] == TEN_TO_THIRTEEN_PREFIX prefix = isbn[3..11] return prefix + self.checkdigit(prefix + '0') end
To convert to an ISBN13, throw a '978' on the front and compute the checkdigit We leave 13-digit numbers alone, figuring they're already ok. NO CHECKSUM CHECK IS DONE FOR 13-DIGIT ISBNS! and return nil on anything that's not the right length @param [String] isbn The ISBN
(we'll try to clean it up if possible) @return [String, nil] The converted 13-character ISBN
, nil if something looks wrong, or whatever was passed in if it already looked like a 13-digit ISBN
# File lib/library_stdnums.rb, line 143 def self.convert_to_13 isbn isbn = reduce_to_basics isbn, [10,13] return nil unless isbn return nil unless valid?(isbn, true) return isbn if isbn.size == 13 prefix = TEN_TO_THIRTEEN_PREFIX + isbn[0..8] return prefix + self.checkdigit(prefix + '0', true) end
For an ISBN
, normalizing it is the same as converting to ISBN
13 and making sure it's valid
@param [String] rawisbn The ISBN
to normalize @return [String, nil] the normalized (to 13 digit) ISBN
, or nil on failure
# File lib/library_stdnums.rb, line 128 def self.normalize rawisbn isbn = convert_to_13 rawisbn if isbn return isbn else return nil end end
Check to see if the checkdigit is correct @param [String] isbn The ISBN
(we'll try to clean it up if possible) @param [Boolean] preprocessed Set to true if the ISBN
has already been through reduce_to_basics @return [Boolean] Whether or not the checkdigit is correct. Sneakily, return 'nil' for
values that don't even look like ISBNs, and 'false' for those that look possible but don't normalize / have bad checkdigits
# File lib/library_stdnums.rb, line 113 def self.valid? isbn, preprocessed = false return nil if isbn.nil? isbn = reduce_to_basics(isbn, [10,13]) unless preprocessed return nil unless isbn return false unless isbn[-1..-1] == self.checkdigit(isbn, true) return false unless isbn.size == 10 || valid_isbn13_prefix?(isbn) return true end
Checks for a valid ISBN13 prefix ISBN13 always starts with 978 or 979. For example: 1000000000012 has a valid check digit, but is not a valid ISBN13. @param [String] isbn13 The ISBN13 to be checked. @return [Boolean] If true then the prefix is valid
# File lib/library_stdnums.rb, line 196 def self.valid_isbn13_prefix?(isbn13) isbn13.size == 13 and !!VALID_THIRTEEN_PREFIX.match(isbn13) end