Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 27 additions & 7 deletions lib/lisbn/lisbn.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,30 @@ def isbn

# Returns true if the ISBN is valid, false otherwise.
def valid?
case isbn.length
when 10
valid_isbn_10?
when 13
valid_isbn_13?
else
false
end
end

# Returns true if the ISBN is valid, false otherwise.
def valid_checksum?
case isbn.length
when 10
valid_isbn_10?
valid_checksum_isbn_10?
when 13
valid_isbn_13?
valid_checksum_isbn_13?
else
false
end
end

def isbn_with_dash
if valid_isbn_13? && parts
if valid_checksum_isbn_13? && parts
parts.join("-")
elsif isbn.length > 3
isbn[0..-2] + "-" + isbn[-1]
Expand All @@ -39,7 +51,7 @@ def isbn10
# Returns a valid ISBN in ISBN-13 format.
# Returns nil if the ISBN is invalid.
def isbn13
return unless valid?
return unless valid_checksum?
return isbn if isbn.length == 13

'978' + isbn[0..-2] + isbn_13_checksum
Expand Down Expand Up @@ -138,19 +150,27 @@ def isbn_13_checksum
(10 - sum % 10).to_s[-1]
end

cache_method :isbn, :valid?, :isbn10, :isbn13, :parts, :isbn_10_checksum, :isbn_13_checksum
cache_method :isbn, :valid?, :valid_checksum?, :isbn10, :isbn13, :parts, :isbn_10_checksum, :isbn_13_checksum

private

def valid_isbn_10?
def valid_checksum_isbn_10?
return false unless isbn.match(/^[0-9]{9}[0-9X]$/)
isbn[-1..-1] == isbn_10_checksum
end

def valid_isbn_13?
def valid_checksum_isbn_13?
return false unless isbn.match(/^[0-9]{13}$/)
isbn[-1..-1] == isbn_13_checksum
end

def valid_isbn_10?
!parts(4).blank?
end

def valid_isbn_13?
!parts.blank?
end

RANGES = YAML::load_file(File.dirname(__FILE__) + "/../../data/ranges.yml")
end
68 changes: 63 additions & 5 deletions spec/lisbn_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,16 @@
isbn.valid?.should be false
end

it "recognizes an invalid ISBN13 with valid checksum" do
isbn = Lisbn.new("8830114722800")
isbn.valid?.should be false
end

it "recognizes an invalid ISBN10 with valid checksum" do
isbn = Lisbn.new("8830114722800")
isbn.valid?.should be false
end

it "returns false for improperly-formatted ISBNs" do
isbn = Lisbn.new("97800000X0002")
isbn.valid?.should be false
Expand All @@ -55,6 +65,54 @@
end
end


describe "#valid_checksum?" do
it "recognizes a valid checksum for ISBN10 format" do
isbn = Lisbn.new("0123456789")
isbn.valid_checksum?.should be true
end

it "recognizes a valid checksum for ISBN10 with X" do
isbn = Lisbn.new("160459411X")
isbn.valid_checksum?.should be true
end

it "recognizes a valid checksum for ISBN10 with 0" do
isbn = Lisbn.new("0679405070")
isbn.valid_checksum?.should be true
end

it "recognizes an invalid ISBN10 checksum" do
isbn = Lisbn.new("0123546789")
isbn.valid_checksum?.should be false
end

it "recognizes a valid checksum for ISBN13 format" do
isbn = Lisbn.new("9780000000002")
isbn.valid_checksum?.should be true
end

it "recognizes a valid checksum for ISBN13 with 0" do
isbn = Lisbn.new("9780062870780")
isbn.valid_checksum?.should be true
end

it "recognizes an invalid checksum for ISBN13" do
isbn = Lisbn.new("9780000000003")
isbn.valid_checksum?.should be false
end

it "returns false for improperly-formatted ISBNs" do
isbn = Lisbn.new("97800000X0002")
isbn.valid_checksum?.should be false
end

it "regards anything not 10 or 13 digits as invalid" do
isbn = Lisbn.new("")
isbn.valid_checksum?.should be false
end
end

describe "#isbn_with_dash" do
subject { Lisbn.new(isbn) }

Expand Down Expand Up @@ -87,13 +145,13 @@
subject { Lisbn.new("9780000000002") }

it "returns nil if invalid" do
subject.stub(:valid? => false)
subject.stub(:valid_checksum? => false)
subject.isbn10.should be_nil
end

it "returns nil if the ISBN is 13-digits and isn't in the 978 GS1" do
lisbn = Lisbn.new("9790000000003")
lisbn.stub(:valid? => true)
lisbn.stub(:valid_checksum? => true)
lisbn.isbn10.should be_nil
end

Expand All @@ -103,7 +161,7 @@

it "returns the isbn if it's 10 digits" do
lisbn = Lisbn.new("0000000000")
lisbn.stub(:valid? => true)
lisbn.stub(:valid_checksum? => true)
lisbn.should_not_receive(:isbn_10_checksum)
lisbn.isbn10.should == "0000000000"
end
Expand All @@ -113,7 +171,7 @@
subject { Lisbn.new("0000000000") }

it "returns nil if invalid" do
subject.stub(:valid? => false)
subject.stub(:valid_checksum? => false)
subject.isbn13.should be_nil
end

Expand All @@ -123,7 +181,7 @@

it "returns the isbn if it's 13 digits" do
lisbn = Lisbn.new("9780000000002")
lisbn.stub(:valid? => true)
lisbn.stub(:valid_checksum? => true)
lisbn.should_not_receive(:isbn_13_checksum)
lisbn.isbn13.should == "9780000000002"
end
Expand Down