Module: StdNum::ISBN

Defined in:
lib/library_stdnums.rb

Class Method Summary collapse

Class Method Details

.checkdigit(isbn) ⇒ String

Compute check digits for 10 or 13-digit ISBNs. See algorithm at en.wikipedia.org/wiki/International_Standard_Book_Number

Parameters:

  • isbn (String)

    The ISBN (we’ll try to clean it up if possible)

Returns:

  • (String)

    the one-character checkdigit



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/library_stdnums.rb', line 21

def self.checkdigit isbn
  isbn = StdNum.extractNumber isbn
  size = isbn.size
  return nil unless size == 10 or size == 13
  checkdigit = 0
  if 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
    digits = isbn[0..11].split(//).map {|i| i.to_i}
    6.times do
      checkdigit += digits.shift
      checkdigit += digits.shift * 3
    end
    return (10 - (checkdigit % 10)).to_s
  end
end

.convert_to_10(isbn) ⇒ String

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.

Parameters:

  • isbn (String)

    The ISBN (we’ll try to clean it up if possible)

Returns:

  • (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



75
76
77
78
79
80
81
82
83
84
# File 'lib/library_stdnums.rb', line 75

def self.convert_to_10 isbn
  isbn = StdNum.extractNumber isbn
  size = isbn.size
  return isbn if size == 10
  return nil unless size == 13
  return nil unless isbn[0..2] == '978'
  
  prefix = isbn[3..11]
  return prefix + self.checkdigit(prefix + '0')
end

.convert_to_13(isbn) ⇒ String

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, and return nil on anything that’s not the right length

Parameters:

  • isbn (String)

    The ISBN (we’ll try to clean it up if possible)

Returns:

  • (String)

    The converted 13-character ISBN, nil if something looks wrong, or whatever was passed in if it already looked like a 13-digit ISBN



60
61
62
63
64
65
66
67
68
# File 'lib/library_stdnums.rb', line 60

def self.convert_to_13 isbn
  isbn = StdNum.extractNumber isbn
  size = isbn.size
  return isbn if size == 13
  return nil unless size == 10

  prefix = '978' + isbn[0..8]
  return prefix + self.checkdigit(prefix + '0')
end

.valid?(isbn) ⇒ Boolean

Check to see if the checkdigit is correct

Parameters:

  • isbn (String)

    The ISBN (we’ll try to clean it up if possible)

Returns:

  • (Boolean)

    Whether or not the checkdigit is correct



47
48
49
50
51
52
# File 'lib/library_stdnums.rb', line 47

def self.valid? isbn
  isbn = StdNum.extractNumber isbn
  size = isbn.size
  return false unless (size == 10 or size == 13)
  return isbn[-1..-1] == self.checkdigit(isbn)
end