Class: Identifiers::ISBN
- Inherits:
-
Object
- Object
- Identifiers::ISBN
- Defined in:
- lib/identifiers/isbn.rb
Constant Summary collapse
- REGEX_13 =
/\b97[89]\d{10}\b/- REGEX_10 =
/\b\d{9}(?:\d|X)\b/- REGEX_A =
%r{\b(?<=10\.)97[89]\.\d{2,8}/\d{1,7}\b}
Class Method Summary collapse
- .digits_of(isbn) ⇒ Object
- .extract(str) ⇒ Object
- .extract_isbn_as(str) ⇒ Object
- .extract_ten_digit_isbns(str) ⇒ Object
- .extract_thirteen_digit_isbns(str) ⇒ Object
- .isbn_13_check_digit(isbn) ⇒ Object
- .valid_isbn_10?(isbn) ⇒ Boolean
- .valid_isbn_13?(isbn) ⇒ Boolean
Class Method Details
.digits_of(isbn) ⇒ Object
56 57 58 |
# File 'lib/identifiers/isbn.rb', line 56 def self.digits_of(isbn) isbn.each_char.map { |char| char == 'X' ? 10 : Integer(char) }.to_enum end |
.extract(str) ⇒ Object
7 8 9 |
# File 'lib/identifiers/isbn.rb', line 7 def self.extract(str) extract_isbn_as(str) + extract_thirteen_digit_isbns(str) + extract_ten_digit_isbns(str) end |
.extract_isbn_as(str) ⇒ Object
11 12 13 |
# File 'lib/identifiers/isbn.rb', line 11 def self.extract_isbn_as(str) extract_thirteen_digit_isbns(str.scan(REGEX_A).join("\n").tr('/.', '')) end |
.extract_ten_digit_isbns(str) ⇒ Object
19 20 21 22 23 24 25 26 27 |
# File 'lib/identifiers/isbn.rb', line 19 def self.extract_ten_digit_isbns(str) str.gsub(/(?<=\d)[- ](?=[\dX])/i, '').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
15 16 17 |
# File 'lib/identifiers/isbn.rb', line 15 def self.extract_thirteen_digit_isbns(str) str.gsub(/(?<=\d)[- ](?=\d)/, '').scan(REGEX_13).select { |isbn| valid_isbn_13?(isbn) } end |
.isbn_13_check_digit(isbn) ⇒ Object
29 30 31 32 33 34 35 36 37 38 |
# File 'lib/identifiers/isbn.rb', line 29 def self.isbn_13_check_digit(isbn) sum = digits_of(isbn).zip([1, 3].cycle).map { |digit, weight| digit * weight }.reduce(:+) check_digit = 10 - (sum % 10) if check_digit == 10 0 else check_digit end end |
.valid_isbn_10?(isbn) ⇒ Boolean
48 49 50 51 52 53 54 |
# File 'lib/identifiers/isbn.rb', line 48 def self.valid_isbn_10?(isbn) return false unless isbn =~ REGEX_10 result = digits_of(isbn).with_index.map { |digit, weight| digit * weight.succ }.reduce(:+) (result % 11).zero? end |
.valid_isbn_13?(isbn) ⇒ Boolean
40 41 42 43 44 45 46 |
# File 'lib/identifiers/isbn.rb', line 40 def self.valid_isbn_13?(isbn) return false unless isbn =~ REGEX_13 result = digits_of(isbn).zip([1, 3].cycle).map { |digit, weight| digit * weight }.reduce(:+) (result % 10).zero? end |