library_stdnums 0.3.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.markdown +92 -0
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/lib/library_stdnums.rb +161 -56
- data/spec/library_stdnums_spec.rb +26 -22
- data/spec/spec_helper.rb +5 -5
- metadata +11 -42
- data/.gitignore +0 -21
- data/CHANGES +0 -9
- data/README.rdoc +0 -23
data/README.markdown
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
# library_stdnums -- simple functions to check and normalize ISSN/ISBN/LCCN
|
2
|
+
|
3
|
+
These are a set of Module functions (not classes with methods!) that perform simple checksum verification and (when applicable) normalization on strings containing common library types (currently just ISBN, ISSN, and LCCN).
|
4
|
+
|
5
|
+
The code allows for some minimal crap (e.g., '1234-4568 online') will work fine. All returned ISBN/ISSN values are devoid any dashes; any trailing X for an ISBN/ISSN checkdigit will be uppercase *and will always be returned as a one-digit string*.
|
6
|
+
|
7
|
+
See the actual functions for more information than what's below.
|
8
|
+
|
9
|
+
## ISBN
|
10
|
+
|
11
|
+
````ruby
|
12
|
+
isbn = StdNum::ISBN.normalize(goodISBN)
|
13
|
+
# => a 13-digit ISBN with no dashes/spaces
|
14
|
+
|
15
|
+
isbn = StdNum::ISBN.normalize(badISBN)
|
16
|
+
# => nil (if it's not an ISBN or the checkdigit is bad)
|
17
|
+
|
18
|
+
tenDigit = StdNum::ISBN.convert_to_10(isbn13)
|
19
|
+
thirteenDigit = StdNum::ISBN.convert_to_13(isbn10)
|
20
|
+
|
21
|
+
thirteenDigit,tenDigit = StdNum::ISBN.allNormalizedValues(issn)
|
22
|
+
# => array of the ten and thirteen digit isbns if valid;
|
23
|
+
# an empty array if not
|
24
|
+
|
25
|
+
digit = StdNum::ISBN.checkdigit(isbn)
|
26
|
+
# => 0..9 (for isbn13) or 0..9,X (for isbn10)
|
27
|
+
|
28
|
+
if StdNum::ISBN.valid?(isbn)
|
29
|
+
puts "#{isbn} has a valid checkdigit"
|
30
|
+
end
|
31
|
+
|
32
|
+
````
|
33
|
+
|
34
|
+
# ISSN
|
35
|
+
|
36
|
+
````ruby
|
37
|
+
issn = StdNum::ISSN.normalize(issn)
|
38
|
+
# => the cleaned-up issn if valid; nil if not
|
39
|
+
|
40
|
+
digit = StdNum::ISSN.checkdigit(issn)
|
41
|
+
# => 0..9 or X
|
42
|
+
|
43
|
+
if StdNum::ISSN.valid?(issn)
|
44
|
+
puts "#{issn} has a valid checkdigit"
|
45
|
+
end
|
46
|
+
````
|
47
|
+
|
48
|
+
# LCCN
|
49
|
+
|
50
|
+
LCCNs are normalized according to the algorithm at http://www.loc.gov/marc/lccn-namespace.html#syntax
|
51
|
+
|
52
|
+
````ruby
|
53
|
+
|
54
|
+
lccn = StdNum::LCCN.normalize(rawlccn)
|
55
|
+
# => either the normalized lccn, or nil if it has bad syntax
|
56
|
+
|
57
|
+
if StdNum::LCCN.valid?(rawlccn) {
|
58
|
+
puts "#{rawlccn} is valid"
|
59
|
+
}
|
60
|
+
````
|
61
|
+
|
62
|
+
== CHANGES
|
63
|
+
|
64
|
+
* 1.0.0
|
65
|
+
* Added normalization all around.
|
66
|
+
* Added valid? for LCCN.
|
67
|
+
* Cleaner code all around, and better docs.
|
68
|
+
* 0.3.0
|
69
|
+
* Wow. ISBN-13 checkdigit wasn't changing '10' to '0'. Blatant error; bad coding *and* testing.
|
70
|
+
* 0.2.2
|
71
|
+
* Added ISSN.valid?
|
72
|
+
* Fixed error in ISSN.checksum when checksum was zero (was returning integer instead of string '0')
|
73
|
+
* 0.2.1
|
74
|
+
* Oops. Forgot to check to make sure there are *any* digits in the ISBN. fixed.
|
75
|
+
* 0.2.0
|
76
|
+
* Added allNormalizedValues for ISBN
|
77
|
+
* 0.1.0
|
78
|
+
* Initial release
|
79
|
+
|
80
|
+
== Note on Patches/Pull Requests
|
81
|
+
|
82
|
+
* Fork the project.
|
83
|
+
* Make your feature addition or bug fix.
|
84
|
+
* Add tests for it. This is important so I don't break it in a
|
85
|
+
future version unintentionally.
|
86
|
+
* Commit, do not mess with rakefile, version, or history.
|
87
|
+
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
88
|
+
* Send me a pull request. Bonus points for topic branches.
|
89
|
+
|
90
|
+
== Copyright
|
91
|
+
|
92
|
+
Copyright (c) 2010 Bill Dueber. See LICENSE for details.
|
data/Rakefile
CHANGED
@@ -10,7 +10,7 @@ begin
|
|
10
10
|
gem.email = "bill@dueber.com"
|
11
11
|
gem.homepage = "http://github.com/billdueber/library_stdnums"
|
12
12
|
gem.authors = ["Bill Dueber"]
|
13
|
-
gem.add_development_dependency "
|
13
|
+
gem.add_development_dependency "minitest", ">= 0" if RUBY_VERSION < "1.9"
|
14
14
|
gem.add_development_dependency "yard", ">= 0"
|
15
15
|
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
16
16
|
end
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
1.0.0
|
data/lib/library_stdnums.rb
CHANGED
@@ -1,30 +1,53 @@
|
|
1
1
|
module StdNum
|
2
|
-
|
3
|
-
STDNUMPAT = /^.*?(\d[\d\-]+[xX]?)/
|
4
|
-
|
5
|
-
# Extract the most likely looking number from the string. This will be the first
|
6
|
-
# string of digits-and-hyphens-and-maybe-a-trailing-X, with the hypens removed
|
7
|
-
def self.extractNumber str
|
8
|
-
match = STDNUMPAT.match str
|
9
|
-
return nil unless match
|
10
|
-
return match[1].gsub(/\-/, '').upcase
|
11
|
-
end
|
12
2
|
|
3
|
+
module Helpers
|
4
|
+
|
5
|
+
STDNUMPAT = /^.*?(\d[\d\-]+[xX]?)/
|
13
6
|
|
7
|
+
# Extract the most likely looking number from the string. This will be the first
|
8
|
+
# string of digits-and-hyphens-and-maybe-a-trailing-X, with the hypens removed
|
9
|
+
def extractNumber str
|
10
|
+
match = STDNUMPAT.match str
|
11
|
+
return nil unless match
|
12
|
+
return match[1].gsub(/\-/, '').upcase
|
13
|
+
end
|
14
|
+
|
15
|
+
def reduce_to_basics rawnum, valid_sizes = nil
|
16
|
+
return nil if rawnum.nil?
|
17
|
+
|
18
|
+
num = extractNumber rawnum
|
19
|
+
|
20
|
+
# Does it even look like a number?
|
21
|
+
return nil unless num
|
22
|
+
|
23
|
+
# Return what we've got if we don't care about the size
|
24
|
+
return num unless valid_sizes
|
25
|
+
|
26
|
+
# Check for valid size(s)
|
27
|
+
[valid_sizes].flatten.each do |s|
|
28
|
+
return num if num.size == s
|
29
|
+
end
|
30
|
+
|
31
|
+
# Didn't check out size-wise. Return nil
|
32
|
+
return nil
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
14
36
|
|
15
37
|
module ISBN
|
38
|
+
extend Helpers
|
16
39
|
|
17
40
|
# Compute check digits for 10 or 13-digit ISBNs. See algorithm at
|
18
41
|
# http://en.wikipedia.org/wiki/International_Standard_Book_Number
|
19
42
|
# @param [String] isbn The ISBN (we'll try to clean it up if possible)
|
20
|
-
# @
|
21
|
-
|
22
|
-
|
43
|
+
# @param [Boolean] preprocessed Set to true if the ISBN has already been through reduce_to_basics
|
44
|
+
# @return [String,nil] the one-character checkdigit, or nil if it's not an ISBN string
|
45
|
+
def self.checkdigit isbn, preprocessed = false
|
46
|
+
isbn = reduce_to_basics isbn, [10,13] unless preprocessed
|
23
47
|
return nil unless isbn
|
24
|
-
|
25
|
-
return nil unless size == 10 or size == 13
|
48
|
+
|
26
49
|
checkdigit = 0
|
27
|
-
if size == 10
|
50
|
+
if isbn.size == 10
|
28
51
|
digits = isbn[0..8].split(//).map {|i| i.to_i}
|
29
52
|
(1..9).each do |i|
|
30
53
|
checkdigit += digits[i-1] * i
|
@@ -47,66 +70,83 @@ module StdNum
|
|
47
70
|
|
48
71
|
# Check to see if the checkdigit is correct
|
49
72
|
# @param [String] isbn The ISBN (we'll try to clean it up if possible)
|
73
|
+
# @param [Boolean] preprocessed Set to true if the ISBN has already been through reduce_to_basics
|
50
74
|
# @return [Boolean] Whether or not the checkdigit is correct
|
51
|
-
def self.valid? isbn
|
52
|
-
|
75
|
+
def self.valid? isbn, preprocessed = false
|
76
|
+
return nil if isbn.nil?
|
77
|
+
isbn = reduce_to_basics(isbn, [10,13]) unless preprocessed
|
53
78
|
return false unless isbn
|
54
|
-
|
55
|
-
return
|
56
|
-
return isbn[-1..-1] == self.checkdigit(isbn)
|
79
|
+
return false unless isbn[-1..-1] == self.checkdigit(isbn, true)
|
80
|
+
return true
|
57
81
|
end
|
58
82
|
|
83
|
+
|
84
|
+
# For an ISBN normalizing it is the same as converting to ISBN 13
|
85
|
+
# and making sure it's valid
|
86
|
+
# @param [String] isbn The ISBN to normalize
|
87
|
+
# @param [Boolean] passthrough On failure, return the original passed-in value instead of nil
|
88
|
+
# @return [String, nil] the normalized (to 13 digit) ISBN, or nil on failure
|
89
|
+
def self.normalize rawisbn
|
90
|
+
isbn = convert_to_13 rawisbn
|
91
|
+
if isbn and valid?(isbn, true)
|
92
|
+
return isbn
|
93
|
+
else
|
94
|
+
return nil
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
59
98
|
# To convert to an ISBN13, throw a '978' on the front and
|
60
99
|
# compute the checkdigit
|
61
|
-
# We leave 13-digit numbers alone, figuring they're already ok
|
100
|
+
# We leave 13-digit numbers alone, figuring they're already ok. NO CHECKSUM CHECK IS DONE FOR 13-DIGIT ISBNS!
|
62
101
|
# and return nil on anything that's not the right length
|
63
102
|
# @param [String] isbn The ISBN (we'll try to clean it up if possible)
|
64
|
-
# @return [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
|
103
|
+
# @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
|
65
104
|
def self.convert_to_13 isbn
|
66
|
-
isbn =
|
105
|
+
isbn = reduce_to_basics isbn, [10,13]
|
67
106
|
return nil unless isbn
|
68
|
-
|
69
|
-
return isbn if size == 13
|
70
|
-
return nil unless size == 10
|
71
|
-
|
107
|
+
return isbn if isbn.size == 13
|
72
108
|
prefix = '978' + isbn[0..8]
|
73
|
-
return prefix + self.checkdigit(prefix + '0')
|
109
|
+
return prefix + self.checkdigit(prefix + '0', true)
|
74
110
|
end
|
75
|
-
|
76
|
-
|
111
|
+
|
112
|
+
|
77
113
|
# Convert to 10 if it's 13 digits and the first three digits are 978.
|
78
114
|
# Pass through anything 10-digits, and return nil for everything else.
|
79
115
|
# @param [String] isbn The ISBN (we'll try to clean it up if possible)
|
80
116
|
# @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
|
81
117
|
def self.convert_to_10 isbn
|
82
|
-
isbn =
|
83
|
-
|
84
|
-
|
85
|
-
return isbn if size == 10
|
86
|
-
|
118
|
+
isbn = reduce_to_basics isbn, [10,13]
|
119
|
+
|
120
|
+
# Already 10 digits? Just return
|
121
|
+
return isbn if isbn.size == 10
|
122
|
+
|
123
|
+
# Can't be converted to ISBN-10? Bail
|
87
124
|
return nil unless isbn[0..2] == '978'
|
88
125
|
|
89
126
|
prefix = isbn[3..11]
|
90
127
|
return prefix + self.checkdigit(prefix + '0')
|
91
128
|
end
|
92
129
|
|
93
|
-
# Return an array of the
|
130
|
+
# Return an array of the ISBN13 and ISBN10 (in that order) for the passed in value. You'll
|
94
131
|
# only get one value back if it's a 13-digit
|
95
132
|
# ISBN that can't be converted to an ISBN10.
|
96
133
|
# @param [String] isbn The original ISBN, in 10-character or 13-digit format
|
97
|
-
# @return [Array] Either the (one or two) normalized ISBNs, or
|
134
|
+
# @return [Array<String,String>, nil] Either the (one or two) normalized ISBNs, or nil if
|
98
135
|
# it can't be recognized.
|
136
|
+
#
|
137
|
+
# @example Get the normalized values and index them (if valid) or original value (if not)
|
138
|
+
# norms = StdNum::ISBN.allNormalizedValues(rawisbn)
|
139
|
+
# doc['isbn'] = norms ? norms : [rawisbn]
|
140
|
+
|
99
141
|
|
100
142
|
def self.allNormalizedValues isbn
|
101
|
-
isbn =
|
143
|
+
isbn = reduce_to_basics isbn, [10,13]
|
102
144
|
return [] unless isbn
|
103
145
|
case isbn.size
|
104
146
|
when 10
|
105
|
-
return [
|
147
|
+
return [self.convert_to_13(isbn), isbn]
|
106
148
|
when 13
|
107
149
|
return [isbn, self.convert_to_10(isbn)].compact
|
108
|
-
else
|
109
|
-
return []
|
110
150
|
end
|
111
151
|
end
|
112
152
|
|
@@ -114,13 +154,17 @@ module StdNum
|
|
114
154
|
end
|
115
155
|
|
116
156
|
module ISSN
|
157
|
+
extend Helpers
|
117
158
|
|
118
159
|
# Compute the checkdigit of an ISSN
|
119
160
|
# @param [String] issn The ISSN (we'll try to clean it up if possible)
|
161
|
+
# @param [Boolean] preprocessed Set to true if the number has already been through reduce_to_basic
|
120
162
|
# @return [String] the one-character checkdigit
|
121
|
-
|
122
|
-
|
123
|
-
|
163
|
+
|
164
|
+
def self.checkdigit issn, preprocessed = false
|
165
|
+
issn = reduce_to_basics issn, 8 unless preprocessed
|
166
|
+
return nil unless issn
|
167
|
+
|
124
168
|
digits = issn[0..6].split(//).map {|i| i.to_i}
|
125
169
|
checkdigit = 0
|
126
170
|
(0..6).each do |i|
|
@@ -135,32 +179,93 @@ module StdNum
|
|
135
179
|
|
136
180
|
# Check to see if the checkdigit is correct
|
137
181
|
# @param [String] isbn The ISSN (we'll try to clean it up if possible)
|
182
|
+
# @param [Boolean] preprocessed Set to true if the number has already been through reduce_to_basic
|
138
183
|
# @return [Boolean] Whether or not the checkdigit is correct
|
139
|
-
|
140
|
-
|
184
|
+
|
185
|
+
def self.valid? issn, preprocessed = false
|
186
|
+
issn = reduce_to_basics issn, 8 unless preprocessed
|
141
187
|
return false unless issn
|
142
|
-
|
143
|
-
return false unless (size == 8)
|
144
|
-
return issn[-1..-1] == self.checkdigit(issn)
|
188
|
+
return issn[-1..-1] == self.checkdigit(issn, true)
|
145
189
|
end
|
146
190
|
|
191
|
+
def self.normalize rawissn
|
192
|
+
issn = reduce_to_basics rawissn, 8
|
193
|
+
if issn and valid?(issn, true)
|
194
|
+
return issn
|
195
|
+
else
|
196
|
+
return nil
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
|
147
201
|
|
148
202
|
end
|
149
203
|
|
150
204
|
module LCCN
|
205
|
+
|
206
|
+
# The rules for validity according to http://www.loc.gov/marc/lccn-namespace.html#syntax:
|
207
|
+
#
|
208
|
+
# A normalized LCCN is a character string eight to twelve characters in length. (For purposes of this description characters are ordered from left to right -- "first" means "leftmost".)
|
209
|
+
# The rightmost eight characters are always digits.
|
210
|
+
# If the length is 9, then the first character must be alphabetic.
|
211
|
+
# If the length is 10, then the first two characters must be either both digits or both alphabetic.
|
212
|
+
# If the length is 11, then the first character must be alphabetic and the next two characters must be either both digits or both alphabetic.
|
213
|
+
# If the length is 12, then the first two characters must be alphabetic and the remaining characters digits.
|
214
|
+
#
|
215
|
+
# @param [String] lccn The lccn to attempt to validate
|
216
|
+
# @param [Boolean] preprocessed Set to true if the number has already been normalized
|
217
|
+
# @return [Boolean] Whether or not the syntax seems ok
|
218
|
+
|
219
|
+
def self.reduce_to_basic str
|
220
|
+
str.gsub!(/\s/, '') # ditch leading spaces
|
221
|
+
str.gsub!(/\/.*$/, '') # ditch everything after the first '/' (including the slash)
|
222
|
+
return str
|
223
|
+
end
|
224
|
+
|
225
|
+
|
226
|
+
def self.valid? lccn, preprocessed = false
|
227
|
+
lccn = normalize(lccn) unless preprocessed
|
228
|
+
return false unless (8..12).include? lccn.size
|
229
|
+
clean = lccn.gsub(/\-/, '')
|
230
|
+
suffix = clean[-8..-1]
|
231
|
+
prefix = clean[0..-9]
|
232
|
+
return false unless suffix =~ /^\d+$/
|
233
|
+
case clean.size
|
234
|
+
when 8
|
235
|
+
return true
|
236
|
+
when 9
|
237
|
+
return true if prefix =~ /[A-Za-z]/
|
238
|
+
when 10
|
239
|
+
return true if prefix =~ /\d{2}/ or prefix =~ /[A-Za-z]{2}/
|
240
|
+
when 11
|
241
|
+
return true if prefix =~ /[A-Za-z](\d{2}|[A-Za-z]{2})/
|
242
|
+
when 12
|
243
|
+
return true if prefix =~ /[A-Za-z]{2}\d{2}/
|
244
|
+
else
|
245
|
+
return false
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
|
250
|
+
|
151
251
|
# Normalize based on data at http://www.loc.gov/marc/lccn-namespace.html#syntax
|
152
252
|
# @param [String] str The LCCN to normalize
|
153
253
|
# @return [String] the normalized LCCN, or nil if it looks malformed
|
154
|
-
def self.normalize
|
155
|
-
|
156
|
-
|
157
|
-
if
|
254
|
+
def self.normalize rawlccn
|
255
|
+
lccn = reduce_to_basic(rawlccn)
|
256
|
+
# If there's a dash in it, deal with that.
|
257
|
+
if lccn =~ /^(.*?)\-(.+)/
|
158
258
|
pre = $1
|
159
259
|
post = $2
|
160
260
|
return nil unless post =~ /^\d+$/ # must be all digits
|
161
|
-
|
261
|
+
lccn = "%s%06d" % [pre, post.to_i]
|
262
|
+
end
|
263
|
+
|
264
|
+
if valid?(lccn, true)
|
265
|
+
return lccn
|
266
|
+
else
|
267
|
+
return nil
|
162
268
|
end
|
163
|
-
return str
|
164
269
|
end
|
165
270
|
end
|
166
271
|
|
@@ -2,31 +2,31 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe "Extract" do
|
4
4
|
it "should leave a number alone" do
|
5
|
-
StdNum.extractNumber('123456').
|
5
|
+
StdNum::ISBN.extractNumber('123456').must_equal '123456'
|
6
6
|
end
|
7
7
|
|
8
8
|
it "should skip leading and trailing crap" do
|
9
|
-
StdNum.extractNumber(' 12345 (online)').
|
9
|
+
StdNum::ISBN.extractNumber(' 12345 (online)').must_equal '12345'
|
10
10
|
end
|
11
11
|
|
12
12
|
it "should allow hyphens" do
|
13
|
-
StdNum.extractNumber(' 1-234-5').
|
13
|
+
StdNum::ISBN.extractNumber(' 1-234-5').must_equal '12345'
|
14
14
|
end
|
15
15
|
|
16
16
|
it "should return nil on a non-match" do
|
17
|
-
StdNum.extractNumber('bill dueber').
|
17
|
+
StdNum::ISBN.extractNumber('bill dueber').must_equal nil
|
18
18
|
end
|
19
19
|
|
20
20
|
it "should allow a trailing X" do
|
21
|
-
StdNum.extractNumber('1-234-5-X').
|
21
|
+
StdNum::ISBN.extractNumber('1-234-5-X').must_equal '12345X'
|
22
22
|
end
|
23
23
|
|
24
24
|
it "should upcase any trailing X" do
|
25
|
-
StdNum.extractNumber('1-234-x').
|
25
|
+
StdNum::ISBN.extractNumber('1-234-x').must_equal '1234X'
|
26
26
|
end
|
27
27
|
|
28
28
|
it "only allows a single trailing X" do
|
29
|
-
StdNum.extractNumber('1234-X-X').
|
29
|
+
StdNum::ISBN.extractNumber('1234-X-X').must_equal '1234X'
|
30
30
|
end
|
31
31
|
|
32
32
|
end
|
@@ -34,52 +34,52 @@ end
|
|
34
34
|
|
35
35
|
describe "ISBN" do
|
36
36
|
it "computes 10-digit checksum" do
|
37
|
-
StdNum::ISBN.checkdigit('0-306-40615-X').
|
37
|
+
StdNum::ISBN.checkdigit('0-306-40615-X').must_equal '2'
|
38
38
|
end
|
39
39
|
|
40
40
|
it "correctly uses X for checksum" do
|
41
|
-
StdNum::ISBN.checkdigit('061871460X').
|
41
|
+
StdNum::ISBN.checkdigit('061871460X').must_equal 'X'
|
42
42
|
end
|
43
43
|
|
44
44
|
it "finds a zero checkdigit" do
|
45
|
-
StdNum::ISBN.checkdigit('0139381430').
|
45
|
+
StdNum::ISBN.checkdigit('0139381430').must_equal '0'
|
46
46
|
end
|
47
47
|
|
48
48
|
it "computes 13-digit checksum" do
|
49
|
-
StdNum::ISBN.checkdigit('9780306406157').
|
49
|
+
StdNum::ISBN.checkdigit('9780306406157').must_equal '7'
|
50
50
|
end
|
51
51
|
|
52
52
|
it "computes a 13-digit checksum that is 0" do
|
53
|
-
StdNum::ISBN.checkdigit('9783837612950').
|
53
|
+
StdNum::ISBN.checkdigit('9783837612950').must_equal '0'
|
54
54
|
end
|
55
55
|
|
56
56
|
it "finds a good number valid" do
|
57
|
-
StdNum::ISBN.valid?('9780306406157').
|
57
|
+
StdNum::ISBN.valid?('9780306406157').must_equal true
|
58
58
|
end
|
59
59
|
|
60
60
|
it "finds a bad number invalid" do
|
61
|
-
StdNum::ISBN.valid?('9780306406154').
|
61
|
+
StdNum::ISBN.valid?('9780306406154').must_equal false
|
62
62
|
end
|
63
63
|
|
64
64
|
it "returns nil when computing checksum for bad ISBN" do
|
65
|
-
StdNum::ISBN.checkdigit('12345').
|
65
|
+
StdNum::ISBN.checkdigit('12345').must_equal nil
|
66
66
|
end
|
67
67
|
|
68
68
|
it "converts 10 to 13" do
|
69
|
-
StdNum::ISBN.convert_to_13('0-306-40615-2').
|
69
|
+
StdNum::ISBN.convert_to_13('0-306-40615-2').must_equal '9780306406157'
|
70
70
|
end
|
71
71
|
|
72
72
|
it "passes through 13 digit number instead of converting to 13" do
|
73
|
-
StdNum::ISBN.convert_to_13('9780306406157').
|
73
|
+
StdNum::ISBN.convert_to_13('9780306406157').must_equal '9780306406157'
|
74
74
|
end
|
75
75
|
|
76
76
|
it "converts 13 to 10" do
|
77
|
-
StdNum::ISBN.convert_to_10('978-0-306-40615-7').
|
77
|
+
StdNum::ISBN.convert_to_10('978-0-306-40615-7').must_equal '0306406152'
|
78
78
|
end
|
79
79
|
|
80
80
|
it "gets both normalized values" do
|
81
81
|
a = StdNum::ISBN.allNormalizedValues('978-0-306-40615-7')
|
82
|
-
a.sort.
|
82
|
+
a.sort.must_equal ['9780306406157', '0306406152' ].sort
|
83
83
|
end
|
84
84
|
|
85
85
|
|
@@ -90,7 +90,11 @@ end
|
|
90
90
|
|
91
91
|
describe 'ISSN' do
|
92
92
|
it "computes checksum" do
|
93
|
-
StdNum::ISSN.checkdigit('0378-5955').
|
93
|
+
StdNum::ISSN.checkdigit('0378-5955').must_equal '5'
|
94
|
+
end
|
95
|
+
|
96
|
+
it "normalizes" do
|
97
|
+
StdNum::ISSN.normalize('0378-5955').must_equal '03785955'
|
94
98
|
end
|
95
99
|
end
|
96
100
|
|
@@ -106,12 +110,12 @@ describe 'LCCN' do
|
|
106
110
|
"85-2 " => "85000002",
|
107
111
|
"2001-000002" => "2001000002",
|
108
112
|
"75-425165//r75" => "75425165",
|
109
|
-
" 79139101 /AC/r932" => "79139101"
|
113
|
+
" 79139101 /AC/r932" => "79139101",
|
110
114
|
}
|
111
115
|
|
112
116
|
test.each do |k, v|
|
113
117
|
it "normalizes #{k}" do
|
114
|
-
StdNum::LCCN.normalize(k.dup).
|
118
|
+
StdNum::LCCN.normalize(k.dup).must_equal v
|
115
119
|
end
|
116
120
|
end
|
117
121
|
|
data/spec/spec_helper.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
require 'rubygems'
|
2
|
-
require 'bacon'
|
3
2
|
begin
|
4
|
-
|
3
|
+
gem 'minitest'
|
5
4
|
rescue LoadError
|
6
5
|
end
|
7
|
-
|
8
|
-
|
6
|
+
|
7
|
+
require 'minitest/spec'
|
8
|
+
require 'minitest/autorun'
|
9
|
+
|
9
10
|
require 'library_stdnums'
|
10
11
|
|
11
|
-
Bacon.summary_on_exit
|
metadata
CHANGED
@@ -1,13 +1,8 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: library_stdnums
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
|
6
|
-
segments:
|
7
|
-
- 0
|
8
|
-
- 3
|
9
|
-
- 0
|
10
|
-
version: 0.3.0
|
4
|
+
prerelease:
|
5
|
+
version: 1.0.0
|
11
6
|
platform: ruby
|
12
7
|
authors:
|
13
8
|
- Bill Dueber
|
@@ -15,37 +10,20 @@ autorequire:
|
|
15
10
|
bindir: bin
|
16
11
|
cert_chain: []
|
17
12
|
|
18
|
-
date: 2011-
|
13
|
+
date: 2011-05-06 00:00:00 -04:00
|
19
14
|
default_executable:
|
20
15
|
dependencies:
|
21
16
|
- !ruby/object:Gem::Dependency
|
22
|
-
name:
|
17
|
+
name: yard
|
23
18
|
prerelease: false
|
24
19
|
requirement: &id001 !ruby/object:Gem::Requirement
|
25
20
|
none: false
|
26
21
|
requirements:
|
27
22
|
- - ">="
|
28
23
|
- !ruby/object:Gem::Version
|
29
|
-
hash: 3
|
30
|
-
segments:
|
31
|
-
- 0
|
32
24
|
version: "0"
|
33
25
|
type: :development
|
34
26
|
version_requirements: *id001
|
35
|
-
- !ruby/object:Gem::Dependency
|
36
|
-
name: yard
|
37
|
-
prerelease: false
|
38
|
-
requirement: &id002 !ruby/object:Gem::Requirement
|
39
|
-
none: false
|
40
|
-
requirements:
|
41
|
-
- - ">="
|
42
|
-
- !ruby/object:Gem::Version
|
43
|
-
hash: 3
|
44
|
-
segments:
|
45
|
-
- 0
|
46
|
-
version: "0"
|
47
|
-
type: :development
|
48
|
-
version_requirements: *id002
|
49
27
|
description: Normalization and checksum computation for ISBN (10 and 13), ISSN, and LCCN
|
50
28
|
email: bill@dueber.com
|
51
29
|
executables: []
|
@@ -54,13 +32,11 @@ extensions: []
|
|
54
32
|
|
55
33
|
extra_rdoc_files:
|
56
34
|
- LICENSE
|
57
|
-
- README.
|
35
|
+
- README.markdown
|
58
36
|
files:
|
59
37
|
- .document
|
60
|
-
- .gitignore
|
61
|
-
- CHANGES
|
62
38
|
- LICENSE
|
63
|
-
- README.
|
39
|
+
- README.markdown
|
64
40
|
- Rakefile
|
65
41
|
- VERSION
|
66
42
|
- lib/library_stdnums.rb
|
@@ -71,8 +47,8 @@ homepage: http://github.com/billdueber/library_stdnums
|
|
71
47
|
licenses: []
|
72
48
|
|
73
49
|
post_install_message:
|
74
|
-
rdoc_options:
|
75
|
-
|
50
|
+
rdoc_options: []
|
51
|
+
|
76
52
|
require_paths:
|
77
53
|
- lib
|
78
54
|
required_ruby_version: !ruby/object:Gem::Requirement
|
@@ -80,26 +56,19 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
80
56
|
requirements:
|
81
57
|
- - ">="
|
82
58
|
- !ruby/object:Gem::Version
|
83
|
-
hash: 3
|
84
|
-
segments:
|
85
|
-
- 0
|
86
59
|
version: "0"
|
87
60
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
88
61
|
none: false
|
89
62
|
requirements:
|
90
63
|
- - ">="
|
91
64
|
- !ruby/object:Gem::Version
|
92
|
-
hash: 3
|
93
|
-
segments:
|
94
|
-
- 0
|
95
65
|
version: "0"
|
96
66
|
requirements: []
|
97
67
|
|
98
68
|
rubyforge_project:
|
99
|
-
rubygems_version: 1.
|
69
|
+
rubygems_version: 1.5.2
|
100
70
|
signing_key:
|
101
71
|
specification_version: 3
|
102
72
|
summary: Normalize and compute checkdigits for ISBN, ISSN, and LCCN
|
103
|
-
test_files:
|
104
|
-
|
105
|
-
- spec/spec_helper.rb
|
73
|
+
test_files: []
|
74
|
+
|
data/.gitignore
DELETED
data/CHANGES
DELETED
@@ -1,9 +0,0 @@
|
|
1
|
-
0.3.0
|
2
|
-
Wow. ISBN-13 checkdigit wasn't changing '10' to '0'. Blatant error; bad coding *and* testing.
|
3
|
-
0.2.2
|
4
|
-
Added ISSN.valid?
|
5
|
-
Fixed error in ISSN.checksum when checksum was zero (was returning integer instead of string '0')
|
6
|
-
0.2.1
|
7
|
-
Oops. Forgot to check to make sure there are *any* digits in the ISBN. fixed.
|
8
|
-
0.2.0
|
9
|
-
Added allNormalizedValues for ISBN
|
data/README.rdoc
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
= library_stdnums
|
2
|
-
|
3
|
-
Do common operations on ISBNs, ISSN, and LCCNs.
|
4
|
-
|
5
|
-
What's supported:
|
6
|
-
|
7
|
-
* *ISBN* Compute or validate checkdigit; convert to/from ISBN-10 and ISBN-13
|
8
|
-
* *ISSN* Compute or validate checkdigit
|
9
|
-
* *LCCN* Normalize
|
10
|
-
|
11
|
-
== Note on Patches/Pull Requests
|
12
|
-
|
13
|
-
* Fork the project.
|
14
|
-
* Make your feature addition or bug fix.
|
15
|
-
* Add tests for it. This is important so I don't break it in a
|
16
|
-
future version unintentionally.
|
17
|
-
* Commit, do not mess with rakefile, version, or history.
|
18
|
-
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
19
|
-
* Send me a pull request. Bonus points for topic branches.
|
20
|
-
|
21
|
-
== Copyright
|
22
|
-
|
23
|
-
Copyright (c) 2010 Bill Dueber. See LICENSE for details.
|