Class: Identifiers::ISBN

Inherits:
Object
  • Object
show all
Defined in:
lib/identifiers/isbn.rb

Constant Summary collapse

REGEX_13 =
/\b97[89]\d{10}\b/
REGEX_10 =
/\b\d{9}(?:\d|X)\b/

Class Method Summary collapse

Class Method Details

.extract(str) ⇒ Object



6
7
8
# File 'lib/identifiers/isbn.rb', line 6

def self.extract(str)
  extract_thirteen_digit_isbns(str) + extract_ten_digit_isbns(str)
end

.extract_ten_digit_isbns(str) ⇒ Object



14
15
16
17
18
19
20
21
22
# File 'lib/identifiers/isbn.rb', line 14

def self.extract_ten_digit_isbns(str)
  str.tr('-', '').scan(REGEX_10).select { |isbn| valid_isbn_10?(isbn) }.map { |isbn|
    isbn.chop!
    isbn.prepend('978')
    isbn << isbn_13_check_digit(isbn).to_s

    isbn
  }
end

.extract_thirteen_digit_isbns(str) ⇒ Object



10
11
12
# File 'lib/identifiers/isbn.rb', line 10

def self.extract_thirteen_digit_isbns(str)
  str.tr('-', '').scan(REGEX_13).select { |isbn| valid_isbn_13?(isbn) }
end

.isbn_13_check_digit(isbn) ⇒ Object



24
25
26
# File 'lib/identifiers/isbn.rb', line 24

def self.isbn_13_check_digit(isbn)
  10 - isbn.each_char.zip([1, 3].cycle).reduce(0) { |sum, values| sum + (Integer(values[0]) * values[1]) } % 10
end

.valid_isbn_10?(isbn) ⇒ Boolean

Returns:

  • (Boolean)


36
37
38
39
40
41
42
43
44
# File 'lib/identifiers/isbn.rb', line 36

def self.valid_isbn_10?(isbn)
  return false unless isbn =~ REGEX_10

  result = isbn.each_char.with_index.reduce(0) { |sum, values|
    sum + (Integer(values[0].sub('X', '10')) * values[1].succ)
  }

  (result % 11).zero?
end

.valid_isbn_13?(isbn) ⇒ Boolean

Returns:

  • (Boolean)


28
29
30
31
32
33
34
# File 'lib/identifiers/isbn.rb', line 28

def self.valid_isbn_13?(isbn)
  return false unless isbn =~ REGEX_13

  result = isbn.each_char.zip([1, 3].cycle).reduce(0) { |sum, values| sum + (Integer(values[0]) * values[1]) }

  (result % 10).zero?
end