From 2bb7547f0efeff505bf79318552ff1db34dda280 Mon Sep 17 00:00:00 2001 From: David Aldridge Date: Sat, 23 Dec 2017 19:36:23 +0000 Subject: [PATCH 1/2] Update documentation (+1 squashed commit) Squashed commits: [68dfa1e] Add publication ranges, for calculating all ISBN13s for a registrant's prefix --- README.md | 18 ++++- lib/lisbn.rb | 1 + lib/lisbn/lisbn.rb | 10 +++ lib/lisbn/publication_range.rb | 54 +++++++++++++ spec/lisbn_spec.rb | 142 ++++++++++++++++++++++++++++++++- 5 files changed, 222 insertions(+), 3 deletions(-) create mode 100644 lib/lisbn/publication_range.rb diff --git a/README.md b/README.md index 0a590ca..ae3a186 100644 --- a/README.md +++ b/README.md @@ -36,12 +36,26 @@ You can convert it to ISBN-10 or ISBN-13: > isbn.isbn13 => "9780000000002" -And you can break it up into its GS1 prefix, group identifier, prefix/publisher code, +You can break it up into its GS1 prefix, group identifier, prefix/publisher code, item number and check digit: > isbn.parts => ["978", "0", "00", "000000", "2"] - + +You can generate the complete range of ISBNs for a registrant element, using the publisher_range object: + + > isbn.publisher_range.isbn13s + => ["9786017002008", "9786017002015", "9786017002022", .. "9786017002992"] + +You can create a publication range object directly: + + > Lisbn::PublicationRange.new("9786017002008") + +You can see the range as a string representation: + + > Lisbn::PublicationRange.new("9786017002008").to_s + => "978-601-7002-00-8..978-601-7002-99-2" + ## Updating You can update the ISBN ranges by replacing the RangeMessage.xml file with an diff --git a/lib/lisbn.rb b/lib/lisbn.rb index 96faa01..4870f16 100644 --- a/lib/lisbn.rb +++ b/lib/lisbn.rb @@ -3,3 +3,4 @@ require_relative "lisbn/cache_method" require_relative "lisbn/lisbn" require_relative "lisbn/ranges" +require_relative "lisbn/publication_range" diff --git a/lib/lisbn/lisbn.rb b/lib/lisbn/lisbn.rb index dcfd55e..d01fd57 100644 --- a/lib/lisbn/lisbn.rb +++ b/lib/lisbn/lisbn.rb @@ -45,6 +45,16 @@ def isbn13 '978' + isbn[0..-2] + isbn_13_checksum end + def isbn13_checksum_corrected + return nil unless isbn.length == 13 + isbn[0..-2] + isbn_13_checksum + end + + def publication_range + return unless isbn13 + PublicationRange.new(isbn13) + end + # Returns an Array with the 'parts' of the ISBN-13 in left-to-right order. # The parts of an ISBN are as follows: # - GS1 prefix diff --git a/lib/lisbn/publication_range.rb b/lib/lisbn/publication_range.rb new file mode 100644 index 0000000..57ee0d8 --- /dev/null +++ b/lib/lisbn/publication_range.rb @@ -0,0 +1,54 @@ +class Lisbn < String + class PublicationRange + def initialize(seed_isbn13) + @seed_isbn13 = Lisbn.new(seed_isbn13) + end + + def parts + seed_isbn13.parts[0..2] + end + + def prefix + parts.join + end + + def to_s + "#{Lisbn.new(from).isbn_with_dash}..#{Lisbn.new(to).isbn_with_dash}" + end + + def number_of_publications + 10 ** (13 - prefix.size - 1) + end + + def publication_numbers + (0..(number_of_publications-1)) + end + + def isbn13s + (from_prefix..to_prefix).to_a.map{|i| Lisbn.new((i*10).to_s).isbn13_checksum_corrected} + end + + private + attr_reader :seed_isbn13 + + def multiplier + (10 ** (12 - prefix.size)) + end + + def from_prefix + prefix.to_i * multiplier + end + + def to_prefix + (prefix.to_i+1) * multiplier - 1 + end + + def from + Lisbn.new((from_prefix*10).to_s).isbn13_checksum_corrected + end + + def to + Lisbn.new((to_prefix*10).to_s).isbn13_checksum_corrected + end + end +end diff --git a/spec/lisbn_spec.rb b/spec/lisbn_spec.rb index 9e11b35..69e3312 100644 --- a/spec/lisbn_spec.rb +++ b/spec/lisbn_spec.rb @@ -127,6 +127,16 @@ lisbn.should_not_receive(:isbn_13_checksum) lisbn.isbn13.should == "9780000000002" end + + it "provides a corrected checksum" do + lisbn = Lisbn.new("9780000000001") + lisbn.isbn13_checksum_corrected.should == "9780000000002" + end + + it "can generate a publication range" do + lisbn = Lisbn.new("9786017002015") + lisbn.publication_range.to_s.should == "978-601-7002-00-8..978-601-7002-99-2" + end end describe "#parts" do @@ -147,6 +157,135 @@ end end + describe "#publication_range" do + subject { Lisbn::PublicationRange.new("9786017002015") } + + it "returns a PublicationRange object" do + subject.class.should == Lisbn::PublicationRange + end + + it "returns the three parts of a PublicationRange" do + subject.parts.should == ["978", "601", "7002"] + end + + it "returns the number of publication in the range" do + subject.number_of_publications.should == 100 + end + + it "returns the range of publication numbers" do + subject.publication_numbers.should == (0..99) + end + + it "returns a string representation of the range of ISBN13s" do + subject.to_s.should == "978-601-7002-00-8..978-601-7002-99-2" + end + + it "returns the range of isbns" do + subject.isbn13s.should == [ + "9786017002008", + "9786017002015", + "9786017002022", + "9786017002039", + "9786017002046", + "9786017002053", + "9786017002060", + "9786017002077", + "9786017002084", + "9786017002091", + "9786017002107", + "9786017002114", + "9786017002121", + "9786017002138", + "9786017002145", + "9786017002152", + "9786017002169", + "9786017002176", + "9786017002183", + "9786017002190", + "9786017002206", + "9786017002213", + "9786017002220", + "9786017002237", + "9786017002244", + "9786017002251", + "9786017002268", + "9786017002275", + "9786017002282", + "9786017002299", + "9786017002305", + "9786017002312", + "9786017002329", + "9786017002336", + "9786017002343", + "9786017002350", + "9786017002367", + "9786017002374", + "9786017002381", + "9786017002398", + "9786017002404", + "9786017002411", + "9786017002428", + "9786017002435", + "9786017002442", + "9786017002459", + "9786017002466", + "9786017002473", + "9786017002480", + "9786017002497", + "9786017002503", + "9786017002510", + "9786017002527", + "9786017002534", + "9786017002541", + "9786017002558", + "9786017002565", + "9786017002572", + "9786017002589", + "9786017002596", + "9786017002602", + "9786017002619", + "9786017002626", + "9786017002633", + "9786017002640", + "9786017002657", + "9786017002664", + "9786017002671", + "9786017002688", + "9786017002695", + "9786017002701", + "9786017002718", + "9786017002725", + "9786017002732", + "9786017002749", + "9786017002756", + "9786017002763", + "9786017002770", + "9786017002787", + "9786017002794", + "9786017002800", + "9786017002817", + "9786017002824", + "9786017002831", + "9786017002848", + "9786017002855", + "9786017002862", + "9786017002879", + "9786017002886", + "9786017002893", + "9786017002909", + "9786017002916", + "9786017002923", + "9786017002930", + "9786017002947", + "9786017002954", + "9786017002961", + "9786017002978", + "9786017002985", + "9786017002992" + ] + end + end + describe "ranges" do it "skips over invalid '0-length' ranges" do Lisbn::RANGES.values.flatten.map {|v| v[:length]}.should_not include(0) @@ -157,7 +296,8 @@ subject { Lisbn.new("9780000000002") } it "#splits" do - subject.split("7").should == ["9", "80000000002"] + subject.split("7").should == ["9", + "80000000002"] end end end From 8345628082622247212b9e37dae6d2fd7625eaa3 Mon Sep 17 00:00:00 2001 From: David Aldridge Date: Thu, 28 Dec 2017 13:31:17 +0000 Subject: [PATCH 2/2] Change publication range isbn13s to an Enumerable --- lib/lisbn/publication_range.rb | 7 +++++-- spec/lisbn_spec.rb | 7 +++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/lib/lisbn/publication_range.rb b/lib/lisbn/publication_range.rb index 57ee0d8..45a1af7 100644 --- a/lib/lisbn/publication_range.rb +++ b/lib/lisbn/publication_range.rb @@ -1,5 +1,6 @@ class Lisbn < String class PublicationRange + include Enumerable def initialize(seed_isbn13) @seed_isbn13 = Lisbn.new(seed_isbn13) end @@ -24,8 +25,10 @@ def publication_numbers (0..(number_of_publications-1)) end - def isbn13s - (from_prefix..to_prefix).to_a.map{|i| Lisbn.new((i*10).to_s).isbn13_checksum_corrected} + def each + (from_prefix..to_prefix).each do |isbn| + yield Lisbn.new((isbn*10).to_s).isbn13_checksum_corrected + end end private diff --git a/spec/lisbn_spec.rb b/spec/lisbn_spec.rb index 69e3312..0efdfc0 100644 --- a/spec/lisbn_spec.rb +++ b/spec/lisbn_spec.rb @@ -180,8 +180,11 @@ subject.to_s.should == "978-601-7002-00-8..978-601-7002-99-2" end - it "returns the range of isbns" do - subject.isbn13s.should == [ + it "returns an enumerable of isbns" do + subject.min.should == "9786017002008" + subject.max.should == "9786017002992" + + subject.map{|x| x}.should == [ "9786017002008", "9786017002015", "9786017002022",