lisbn 0.2.4 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 8fa75ed8a6e119ea7c617805974f13001ec8c138
4
- data.tar.gz: e0eda6505a9276ec0e853e3ebe4f28fea3b3b63c
2
+ SHA256:
3
+ metadata.gz: 775f300f160de6abd661522d46324737767b6b833788a6100bbe2a919b0389e1
4
+ data.tar.gz: 814805f91620600eca86134a2bc6bce92a62ba958b3bcdf126620a0cfc81420b
5
5
  SHA512:
6
- metadata.gz: d87d6a6cf62296f315b9ed195eb79ddf5cc4fce259d84e7fd662ee1f8a64b0da43f48a95af12e92fa93c45a4e44ad9087adea14bf7698fc2bc8f7fbad1f821bb
7
- data.tar.gz: d7cda1db814e7615a191c036211bf673ab247917b2ee2ab8579cc6e54a3a506dd86e1afc7107fe626c21cc2f53c318dbf61e85ce767b1974e61a9d1ab95e07b2
6
+ metadata.gz: a9a6de31ee4669739e39f77705c4019569368c115152dfa811d71215f5a61aa7e59ebe20ca4abc4c472c5cb358fdb1dd16b6f5ff7d23202053f3222fe81a101c
7
+ data.tar.gz: 8804bee7122817fdd1c25af7fa01289eac805d363e654fc4c0b558c8955d731c0405e121a63949b1611b6e1a3930eb0f673647e39cef8170ed14fa0463f10447
@@ -0,0 +1,11 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.5
4
+ deploy:
5
+ provider: rubygems
6
+ api_key:
7
+ secure: fAmrDgaEj29FTiwB/Iy4pX+QiLHTo4MbUw1JeUqMAK/RgDlx0OnTK7J25hfZYScb2tr7xliooC4abQAIzzdrT8J1Pb4qp53G4pwiVcbvf+bXWHJDZDGxNAeGDsvB4EEHhPWJCajIOkx7qEf1+R7Je82MjppeqC0EXx+AO3tDTfQ=
8
+ gem: lisbn
9
+ on:
10
+ tags: true
11
+ repo: ragalie/lisbn
data/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # Lisbn
2
2
 
3
+ [![Build Status](https://travis-ci.org/ragalie/lisbn.svg?branch=master)](https://travis-ci.org/ragalie/lisbn)
4
+
3
5
  Lisbn (pronounced "Lisbon") is a wrapper around String that adds methods for manipulating
4
6
  [ISBNs](http://en.wikipedia.org/wiki/International_Standard_Book_Number).
5
7
 
@@ -58,3 +60,9 @@ Then run:
58
60
  3. Commit your changes (`git commit -am 'Added some feature'`)
59
61
  4. Push to the branch (`git push origin my-new-feature`)
60
62
  5. Create new Pull Request
63
+
64
+ ## Releasing
65
+
66
+ 1. Update the version in lisbn.gemspec using [semver](https://semver.org).
67
+ 2. Tag the version update commit as `vX.X.X` on the master branch.
68
+ 3. Push to github.
data/Rakefile CHANGED
@@ -3,5 +3,11 @@ require "bundler/gem_tasks"
3
3
 
4
4
  Dir["tasks/**/*.rake"].each { |ext| load ext }
5
5
 
6
- require 'rspec/core/rake_task'
7
- RSpec::Core::RakeTask.new('spec')
6
+ begin
7
+ require 'rspec/core/rake_task'
8
+ RSpec::Core::RakeTask.new('spec')
9
+
10
+ task :default => :spec
11
+ rescue LoadError
12
+ # nop
13
+ end
@@ -5,7 +5,7 @@ class Lisbn < String
5
5
  alias_method method + "_without_cache", method
6
6
  define_method method do |*args, &blk|
7
7
  @cache ||= {}
8
- @cache[[method, self]] ||= send(method + "_without_cache", *args, &blk)
8
+ @cache[[method, args, blk, self]] ||= send(method + "_without_cache", *args, &blk)
9
9
  end
10
10
  end
11
11
  end
@@ -17,8 +17,10 @@ class Lisbn < String
17
17
  end
18
18
 
19
19
  def isbn_with_dash
20
- if valid_isbn_13? && parts
21
- parts.join("-")
20
+ if valid_isbn_13? && parts5 = parts(5)
21
+ parts5.join("-")
22
+ elsif valid_isbn_10? && parts4 = parts(4)
23
+ parts4.join("-")
22
24
  elsif isbn.length > 3
23
25
  isbn[0..-2] + "-" + isbn[-1]
24
26
  else
@@ -45,18 +47,21 @@ class Lisbn < String
45
47
  '978' + isbn[0..-2] + isbn_13_checksum
46
48
  end
47
49
 
48
- # Returns an Array with the 'parts' of the ISBN-13 in left-to-right order.
50
+ # Returns an Array with the 'parts' of the ISBN in left-to-right order.
49
51
  # The parts of an ISBN are as follows:
50
- # - GS1 prefix
52
+ # - GS1 prefix (only for ISBN-13)
51
53
  # - Group identifier
52
54
  # - Prefix/publisher code
53
55
  # - Item number
54
56
  # - Check digit
55
57
  #
56
58
  # Returns nil if the ISBN is not valid.
59
+ # Returns nil if parts argument is 4 but ISBN-10 does not exist
57
60
  # Returns nil if the group and prefix cannot be identified.
58
- def parts
61
+ def parts(parts = 5)
62
+ raise ArgumentError, "Parts must be either 4 or 5." unless parts == 4 || parts == 5
59
63
  return unless isbn13
64
+ return if parts == 4 && !isbn10
60
65
 
61
66
  group = prefix = nil
62
67
 
@@ -80,36 +85,59 @@ class Lisbn < String
80
85
  return unless group && prefix
81
86
 
82
87
  prefix = sprintf("%0#{prefix[:length]}d", prefix[:number])
83
- [group[0..2], group[3..-1], prefix, isbn13[(group.length + prefix.length)..-2], isbn13[-1..-1]]
88
+
89
+ if parts == 4
90
+ [group[3..-1], prefix, isbn10[(group[3..-1].length + prefix.length)..-2], isbn10[-1..-1]]
91
+ else
92
+ [group[0..2], group[3..-1], prefix, isbn13[(group.length + prefix.length)..-2], isbn13[-1..-1]]
93
+ end
84
94
  end
85
95
 
86
96
  def isbn_10_checksum
87
97
  base = isbn.length == 13 ? isbn[3..-2] : isbn[0..-2]
88
98
 
89
- products = base.each_char.each_with_index.map do |chr, i|
90
- chr.to_i * (10 - i)
91
- end
99
+ sum = base[0].to_i * 10 +
100
+ base[1].to_i * 9 +
101
+ base[2].to_i * 8 +
102
+ base[3].to_i * 7 +
103
+ base[4].to_i * 6 +
104
+ base[5].to_i * 5 +
105
+ base[6].to_i * 4 +
106
+ base[7].to_i * 3 +
107
+ base[8].to_i * 2
108
+
109
+ remainder = sum % 11
92
110
 
93
- remainder = products.inject(0) {|m, v| m + v} % 11
94
111
  case remainder
95
112
  when 0
96
- 0
113
+ "0"
97
114
  when 1
98
- 'X'
115
+ "X"
99
116
  else
100
- 11 - remainder
101
- end.to_s
117
+ (11 - remainder).to_s
118
+ end
102
119
  end
103
120
 
104
121
  def isbn_13_checksum
105
122
  base = (isbn.length == 13 ? '' : '978') + isbn[0..-2]
106
123
 
107
- products = base.each_char.each_with_index.map do |chr, i|
108
- chr.to_i * (i % 2 == 0 ? 1 : 3)
109
- end
110
-
111
- remainder = products.inject(0) {|m, v| m + v} % 10
112
- (remainder == 0 ? 0 : 10 - remainder).to_s
124
+ sum = (
125
+ base[1].to_i +
126
+ base[3].to_i +
127
+ base[5].to_i +
128
+ base[7].to_i +
129
+ base[9].to_i +
130
+ base[11].to_i
131
+ ) * 3 +
132
+ base[0].to_i +
133
+ base[2].to_i +
134
+ base[4].to_i +
135
+ base[6].to_i +
136
+ base[8].to_i +
137
+ base[10].to_i +
138
+ base[12].to_i
139
+
140
+ (10 - sum % 10).to_s[-1]
113
141
  end
114
142
 
115
143
  cache_method :isbn, :valid?, :isbn10, :isbn13, :parts, :isbn_10_checksum, :isbn_13_checksum
@@ -12,9 +12,11 @@ Gem::Specification.new do |gem|
12
12
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
13
13
  gem.name = "lisbn"
14
14
  gem.require_paths = ["lib"]
15
- gem.version = "0.2.4"
15
+ gem.version = "0.3.0"
16
16
 
17
17
  gem.add_dependency "nori", "~> 2.0"
18
18
  gem.add_dependency "nokogiri"
19
+ gem.add_development_dependency "multi_json"
20
+ gem.add_development_dependency "rake"
19
21
  gem.add_development_dependency "rspec"
20
22
  end
@@ -3,8 +3,8 @@ require 'spec_helper'
3
3
  class String
4
4
  extend Lisbn::CacheMethod
5
5
 
6
- def with_excitement!
7
- self + "!"
6
+ def with_excitement!(how_much = 1)
7
+ self + "!" * how_much
8
8
  end
9
9
 
10
10
  cache_method :with_excitement!
@@ -14,14 +14,27 @@ describe "cache_method" do
14
14
  subject { String.new("awesomeness") }
15
15
 
16
16
  it "evaluates the method the first time but not subsequent times" do
17
- subject.should_receive(:+).with("!").once.and_return("you got stubbed!")
17
+ expect(subject).to receive(:+).with("!").once.and_call_original
18
18
  subject.with_excitement!
19
- subject.with_excitement!.should == "you got stubbed!"
19
+ subject.with_excitement!
20
+ end
21
+
22
+ it "reevaluates the method if the arguments change" do
23
+ expect(subject).to receive(:+).with("!")
24
+ expect(subject).to receive(:+).with("!!")
25
+ subject.with_excitement!
26
+ subject.with_excitement!(2)
27
+ end
28
+
29
+ it "reevaluates the method if the block changes" do
30
+ expect(subject).to receive(:+).twice.and_call_original
31
+ subject.with_excitement! { "cats" }
32
+ subject.with_excitement! { "dogs" }
20
33
  end
21
34
 
22
35
  it "reevaluates the method if the object's hash changes" do
23
- subject.with_excitement!.should == "awesomeness!"
36
+ expect(subject.with_excitement!).to eq("awesomeness!")
24
37
  subject.replace("more awesomeness")
25
- subject.with_excitement!.should == "more awesomeness!"
38
+ expect(subject.with_excitement!).to eq("more awesomeness!")
26
39
  end
27
40
  end
@@ -4,54 +4,54 @@ describe "Lisbn" do
4
4
  describe "#isbn" do
5
5
  it "converts the string to just digits and X" do
6
6
  isbn = Lisbn.new("9487-028asdfasdf878X7")
7
- isbn.isbn.should == "9487028878X7"
7
+ expect(isbn.isbn).to eq("9487028878X7")
8
8
  end
9
9
  end
10
10
 
11
11
  describe "#valid?" do
12
12
  it "recognizes a valid ISBN10" do
13
13
  isbn = Lisbn.new("0123456789")
14
- isbn.valid?.should be true
14
+ expect(isbn.valid?).to be true
15
15
  end
16
16
 
17
17
  it "recognizes a valid ISBN10 with X checksum" do
18
18
  isbn = Lisbn.new("160459411X")
19
- isbn.valid?.should be true
19
+ expect(isbn.valid?).to be true
20
20
  end
21
21
 
22
22
  it "recognizes a valid ISBN10 with 0 checksum" do
23
23
  isbn = Lisbn.new("0679405070")
24
- isbn.valid?.should be true
24
+ expect(isbn.valid?).to be true
25
25
  end
26
26
 
27
27
  it "recognizes an invalid ISBN10" do
28
28
  isbn = Lisbn.new("0123546789")
29
- isbn.valid?.should be false
29
+ expect(isbn.valid?).to be false
30
30
  end
31
31
 
32
32
  it "recognizes a valid ISBN13" do
33
33
  isbn = Lisbn.new("9780000000002")
34
- isbn.valid?.should be true
34
+ expect(isbn.valid?).to be true
35
35
  end
36
36
 
37
37
  it "recognizes a valid ISBN13 with 0 checksum" do
38
38
  isbn = Lisbn.new("9780062870780")
39
- isbn.valid?.should be true
39
+ expect(isbn.valid?).to be true
40
40
  end
41
41
 
42
42
  it "recognizes an invalid ISBN13" do
43
43
  isbn = Lisbn.new("9780000000003")
44
- isbn.valid?.should be false
44
+ expect(isbn.valid?).to be false
45
45
  end
46
46
 
47
47
  it "returns false for improperly-formatted ISBNs" do
48
48
  isbn = Lisbn.new("97800000X0002")
49
- isbn.valid?.should be false
49
+ expect(isbn.valid?).to be false
50
50
  end
51
51
 
52
52
  it "regards anything not 10 or 13 digits as invalid" do
53
53
  isbn = Lisbn.new("")
54
- isbn.valid?.should be false
54
+ expect(isbn.valid?).to be false
55
55
  end
56
56
  end
57
57
 
@@ -69,8 +69,16 @@ describe "Lisbn" do
69
69
  context "with a 10-digit ISBN" do
70
70
  let(:isbn) { "1402780591" }
71
71
 
72
+ it "returns the isbn with dashes between the parts" do
73
+ expect(subject.isbn_with_dash).to eq("1-4027-8059-1")
74
+ end
75
+ end
76
+
77
+ context "with an invalid 9-digit ISBN" do
78
+ let(:isbn) { "402780591" }
79
+
72
80
  it "returns the isbn with a dash before the checkdigit" do
73
- expect(subject.isbn_with_dash).to eq("140278059-1")
81
+ expect(subject.isbn_with_dash).to eq("40278059-1")
74
82
  end
75
83
  end
76
84
 
@@ -87,25 +95,25 @@ describe "Lisbn" do
87
95
  subject { Lisbn.new("9780000000002") }
88
96
 
89
97
  it "returns nil if invalid" do
90
- subject.stub(:valid? => false)
91
- subject.isbn10.should be_nil
98
+ allow(subject).to receive(:valid?) { false }
99
+ expect(subject.isbn10).to be_nil
92
100
  end
93
101
 
94
102
  it "returns nil if the ISBN is 13-digits and isn't in the 978 GS1" do
95
103
  lisbn = Lisbn.new("9790000000003")
96
- lisbn.stub(:valid? => true)
97
- lisbn.isbn10.should be_nil
104
+ allow(lisbn).to receive(:valid?) { true }
105
+ expect(lisbn.isbn10).to be_nil
98
106
  end
99
107
 
100
108
  it "computes the ISBN10 checksum" do
101
- subject.isbn10.should == "0000000000"
109
+ expect(subject.isbn10).to eq("0000000000")
102
110
  end
103
111
 
104
112
  it "returns the isbn if it's 10 digits" do
105
113
  lisbn = Lisbn.new("0000000000")
106
- lisbn.stub(:valid? => true)
107
- lisbn.should_not_receive(:isbn_10_checksum)
108
- lisbn.isbn10.should == "0000000000"
114
+ allow(lisbn).to receive(:valid?) { true }
115
+ expect(lisbn).not_to receive(:isbn_10_checksum)
116
+ expect(lisbn.isbn10).to eq("0000000000")
109
117
  end
110
118
  end
111
119
 
@@ -113,19 +121,19 @@ describe "Lisbn" do
113
121
  subject { Lisbn.new("0000000000") }
114
122
 
115
123
  it "returns nil if invalid" do
116
- subject.stub(:valid? => false)
117
- subject.isbn13.should be_nil
124
+ allow(subject).to receive(:valid?) { false }
125
+ expect(subject.isbn13).to be_nil
118
126
  end
119
127
 
120
128
  it "computes the ISBN13 checksum" do
121
- subject.isbn13.should == "9780000000002"
129
+ expect(subject.isbn13).to eq("9780000000002")
122
130
  end
123
131
 
124
132
  it "returns the isbn if it's 13 digits" do
125
133
  lisbn = Lisbn.new("9780000000002")
126
- lisbn.stub(:valid? => true)
127
- lisbn.should_not_receive(:isbn_13_checksum)
128
- lisbn.isbn13.should == "9780000000002"
134
+ allow(lisbn).to receive(:valid?) { true }
135
+ expect(lisbn).not_to receive(:isbn_13_checksum)
136
+ expect(lisbn.isbn13).to eq("9780000000002")
129
137
  end
130
138
  end
131
139
 
@@ -133,23 +141,74 @@ describe "Lisbn" do
133
141
  subject { Lisbn.new("9780000000002") }
134
142
 
135
143
  it "splits into the right groups" do
136
- subject.parts.should == ["978", "0", "00", "000000", "2"]
144
+ expect(subject.parts).to eq(["978", "0", "00", "000000", "2"])
137
145
  end
138
146
 
139
147
  it "works with long groups" do
140
148
  lisbn = Lisbn.new("9786017002015")
141
- lisbn.parts.should == ["978", "601", "7002", "01", "5"]
149
+ expect(lisbn.parts).to eq(["978", "601", "7002", "01", "5"])
150
+ end
151
+
152
+ it "should raise ArgumentError for anything other than 4 or 5" do
153
+ expect { subject.parts(3) }.to raise_error(ArgumentError)
154
+ end
155
+
156
+ it "splits into the right groups with number argument" do
157
+ expect(subject.parts(5)).to eq(["978", "0", "00", "000000", "2"])
142
158
  end
143
159
 
144
160
  it "returns nil if it can't find a valid group" do
145
161
  lisbn = Lisbn.new("9780100000002")
146
- lisbn.parts.should be_nil
162
+ expect(lisbn.parts).to be_nil
163
+ end
164
+
165
+ it "uses the correct check digit if provided an isbn10" do
166
+ lisbn = Lisbn.new("0906212731")
167
+ expect(lisbn.parts).to eq(["978", "0", "906212", "73", "8"])
168
+ end
169
+
170
+ context "4 parts variant" do
171
+ it "splits isbn10 for parts with argument" do
172
+ lisbn = Lisbn.new("832100928X")
173
+ expect(lisbn.parts(4)).to eq(["83", "210", "0928", "X"])
174
+ end
175
+
176
+ it "works correctly for publisher identifier (CRC Press)" do
177
+ lisbn = Lisbn.new("0849304768")
178
+ expect(lisbn.parts(4)).to eq(["0", "8493", "0476", "8"])
179
+ end
180
+
181
+ it "works correctly with long publisher identifier (Tarquin Publications)" do
182
+ lisbn = Lisbn.new("0906212731")
183
+ expect(lisbn.parts(4)).to eq(["0", "906212", "73", "1"])
184
+ end
185
+
186
+ it "uses the correct check digit if provided an isbn13" do
187
+ lisbn = Lisbn.new("9780906212738")
188
+ expect(lisbn.parts(4)).to eq(["0", "906212", "73", "1"])
189
+ end
190
+
191
+ it "splits isbn10 for parts for initial isbn13" do
192
+ lisbn = Lisbn.new("9786017002015")
193
+ expect(lisbn.parts(4)).to eq(["601", "7002", "01", "5"])
194
+ end
195
+
196
+ it 'returns nil if ISBN-10 equivalent doesnt exists' do
197
+ lisbn = Lisbn.new("979-11-86178-14-0")
198
+ expect(lisbn.parts(4)).to be_nil
199
+ end
200
+
201
+ it "returns nil if it can't find a valid group" do
202
+ lisbn = Lisbn.new("9780100000002")
203
+ expect(lisbn.parts(4)).to be_nil
204
+ end
147
205
  end
148
206
  end
149
207
 
150
208
  describe "ranges" do
151
209
  it "skips over invalid '0-length' ranges" do
152
- Lisbn::RANGES.values.flatten.map {|v| v[:length]}.should_not include(0)
210
+ range_lengths = Lisbn::RANGES.values.flatten.map {|v| v[:length]}
211
+ expect(range_lengths).not_to include(0)
153
212
  end
154
213
  end
155
214
 
@@ -157,7 +216,7 @@ describe "Lisbn" do
157
216
  subject { Lisbn.new("9780000000002") }
158
217
 
159
218
  it "#splits" do
160
- subject.split("7").should == ["9", "80000000002"]
219
+ expect(subject.split("7")).to eq(["9", "80000000002"])
161
220
  end
162
221
  end
163
222
  end
@@ -1,7 +1,6 @@
1
1
  require 'lisbn'
2
2
 
3
3
  RSpec.configure do |config|
4
- config.treat_symbols_as_metadata_keys_with_true_values = true
5
4
  config.run_all_when_everything_filtered = true
6
5
  config.filter_run :focus
7
6
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lisbn
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.4
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mike Ragalie
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-12-26 00:00:00.000000000 Z
11
+ date: 2019-01-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nori
@@ -38,6 +38,34 @@ dependencies:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: multi_json
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
41
69
  - !ruby/object:Gem::Dependency
42
70
  name: rspec
43
71
  requirement: !ruby/object:Gem::Requirement
@@ -62,6 +90,7 @@ extra_rdoc_files: []
62
90
  files:
63
91
  - ".gitignore"
64
92
  - ".rspec"
93
+ - ".travis.yml"
65
94
  - Gemfile
66
95
  - LICENSE
67
96
  - README.md
@@ -95,8 +124,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
95
124
  - !ruby/object:Gem::Version
96
125
  version: '0'
97
126
  requirements: []
98
- rubyforge_project:
99
- rubygems_version: 2.5.2
127
+ rubygems_version: 3.0.2
100
128
  signing_key:
101
129
  specification_version: 4
102
130
  summary: Provides methods for converting between ISBN-10 and ISBN-13, checking validity