barcodevalidation 2.1.0 → 2.4.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: 897dd3cdb0c9e0bf7d9f50bfeb98b0ac8be7b79d
4
- data.tar.gz: 93fb7cc3b723a9ce5c935c6eba57bfadad217d6a
2
+ SHA256:
3
+ metadata.gz: 6aa7aea902c16d451d7a53b8b69979013f1b8d438165cf8f4c3c3940be359047
4
+ data.tar.gz: ea0ca124f7e9e5cdf919c791747f3663215ab33f073140832a88e936a6f11a9b
5
5
  SHA512:
6
- metadata.gz: 5a6cee629384d5ff836f8ca9df2a29bbbd3a982498cd3d5f232bfd5b8b86dde9c6cbc569ae2ca01658fd0b887d24c185e5ee523ff82b90f21aa2f280e133b21d
7
- data.tar.gz: 2d6659bfb3bf670a7b28d7c55e25ecc81412706421ffeee3ea19043f0d28df50e16d7e4f51d0f6f093d959435725e48d38c74b771af1d5f50229499654a07809
6
+ metadata.gz: cbc4e8901c64e54995f4f62dec98e3711a386b88dd693bacc571e22ea4f3e7ae48a6910a75c562456b8e7c788a65a18b1c571395c34a129f3a4da9844e9782a6
7
+ data.tar.gz: ee148eacfcae331bbcc83fa454ed564024668145e3580d01f21cc21622d976bd2f9ac17872c69b7eb63050e040edd7fb69223f640ec3407aeea59abb3f4d0a64
data/README.md CHANGED
@@ -1,11 +1,11 @@
1
1
  barcodevalidation
2
2
  =================
3
3
 
4
- [![Build Status][travis-badge]][travis]
4
+ [![Build Status][ci-badge]][ci]
5
5
  [![Gem Version][rubygems-badge]][rubygems]
6
6
 
7
- [travis]: <https://travis-ci.org/marketplacer/barcodevalidation>
8
- [travis-badge]: <https://travis-ci.org/marketplacer/barcodevalidation.svg?branch=master>
7
+ [ci]: <https://buildkite.com/marketplacer/barcodevalidation>
8
+ [ci-badge]: <https://badge.buildkite.com/d0d578653bc319cd41e9adb2ac23f1c0d59cf56ee6cc329d78.svg?branch=main>
9
9
  [rubygems]: <https://badge.fury.io/rb/barcodevalidation>
10
10
  [rubygems-badge]: <https://badge.fury.io/rb/barcodevalidation.svg>
11
11
 
@@ -40,20 +40,26 @@ and it's pretty flexible about what you give it.
40
40
 
41
41
  ```ruby
42
42
  gtin = BarcodeValidation.scan("937179-004167")
43
- # => #<BarcodeValidation::GTIN(937179004167)>
43
+ # => #<BarcodeValidation::GTIN::GTIN12(937179004167)>
44
44
  gtin.to_s # => "937179004167"
45
45
  gtin.valid? # => true
46
46
  gtin.check_digit # => #<BarcodeValidation::GTIN::CheckDigit(7)>
47
47
  gtin.first(6) # => #<BarcodeValidation::DigitSequence(937179)>
48
48
  gtin.slice(0..5) # => #<BarcodeValidation::DigitSequence(937179)>
49
+ gtin.to_gtin_13 # => #<BarcodeValidation::GTIN::GTIN13(0937179004167)>
50
+ gtin.to_all_valid
51
+ # => [#<BarcodeValidation::GTIN::GTIN12(937179004167)>,
52
+ #<BarcodeValidation::GTIN::GTIN123(0937179004167)>]
49
53
 
50
54
  bad = BarcodeValidation.scan(937_179_004_162)
51
- # => #<BarcodeValidation::GTIN(937179004162)>
55
+ # => #<BarcodeValidation::InvalidGTIN(937179004162)>
52
56
  bad.valid? # => false
53
57
  bad.check_digit # => #<BarcodeValidation::GTIN::CheckDigit(2) invalid: expected 7>
54
58
  bad.check_digit.valid? # => false
55
59
  bad.check_digit.actual # => #<BarcodeValidation::Digit(2)>
56
60
  bad.check_digit.expected # => #<BarcodeValidation::Digit(7)>
61
+ bad.to_gtin_13 # => #<BarcodeValidation::InvalidGTIN(937179004162)>
62
+ bad.to_all_valid # => []
57
63
  ```
58
64
 
59
65
 
@@ -97,11 +103,10 @@ bin/rubocop --help
97
103
 
98
104
 
99
105
 
100
- Continuous Integration
106
+ Tests & Publishing
101
107
  ----------------------
102
108
 
103
- Code is automatically tested with each push, on both Travis CI and
104
- Marketplacer's internal Buildkite.
109
+ Code is automatically tested with each push on Buildkite. Assuming all tests pass, commits on `main` will be parsed with [Semantic Release](https://github.com/semantic-release/semantic-release) to produce new Git tags, and to publish to RubyGems.
105
110
 
106
111
 
107
112
 
@@ -133,4 +138,4 @@ This project is licensed under the [MIT License]. See [LICENSE.md] for
133
138
  the full text.
134
139
 
135
140
  [MIT License]: <https://opensource.org/licenses/MIT>
136
- [LICENSE.md]: <https://github.com/marketplacer/barcodevalidation/blob/master/LICENSE.md>
141
+ [LICENSE.md]: <https://github.com/marketplacer/barcodevalidation/blob/main/LICENSE.md>
@@ -1,9 +1,11 @@
1
- # coding: utf-8
2
- lib = File.expand_path("../lib", __FILE__)
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path("lib", __dir__)
3
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
5
  require "barcodevalidation/version"
5
6
 
6
7
  Gem::Specification.new do |spec|
8
+ spec.required_ruby_version = ">= 2.5"
7
9
  spec.name = "barcodevalidation"
8
10
  spec.version = BarcodeValidation::VERSION
9
11
  spec.authors = ["Marketplacer"]
@@ -14,14 +16,12 @@ Gem::Specification.new do |spec|
14
16
  spec.homepage = "https://github.com/marketplacer/#{spec.name}"
15
17
  spec.license = "MIT"
16
18
 
17
- spec.files = %w(LICENSE.md README.md barcodevalidation.gemspec
18
- config/*.rb lib/**/*.rb)
19
+ spec.files = %w[LICENSE.md README.md barcodevalidation.gemspec
20
+ config/*.rb lib/**/*.rb]
19
21
  .flat_map { |pattern| Dir.glob(pattern) }
20
22
  .reject { |f| File.directory?(f) }
21
23
  spec.bindir = "exe"
22
24
  spec.executables = spec.files
23
25
  .grep(%r{^exe/}) { |f| File.basename(f) }
24
26
  spec.require_paths = ["lib"]
25
-
26
- spec.add_runtime_dependency "adamantium"
27
27
  end
data/config/boot.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # This script sets up the common environment for the project
2
4
  #
3
5
  # Require this file using:
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "delegate"
4
+ require_relative "error/argument_error_class"
2
5
 
3
6
  module BarcodeValidation
4
7
  class Digit < DelegateClass(Integer)
5
- include Adamantium
6
8
  include Mixin::ValueObject
7
9
 
8
10
  INTEGER_CAST_ERRORS = [::ArgumentError, ::TypeError].freeze
@@ -10,6 +12,7 @@ module BarcodeValidation
10
12
  def initialize(input)
11
13
  value = Integer(input)
12
14
  raise ::ArgumentError unless (0..9).cover? value
15
+
13
16
  super(value)
14
17
  rescue *INTEGER_CAST_ERRORS
15
18
  raise Digit::ArgumentError, input
@@ -1,9 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "forwardable"
4
+ require_relative "error/argument_error_class"
2
5
 
3
6
  module BarcodeValidation
4
7
  class DigitSequence < Array
5
8
  extend Forwardable
6
- include Adamantium::Flat
7
9
  include Mixin::ValueObject
8
10
 
9
11
  delegate to_s: :join
@@ -18,6 +20,7 @@ module BarcodeValidation
18
20
  def initialize(values)
19
21
  values = cast(values)
20
22
  raise ArgumentError, values unless values.respond_to? :map
23
+
21
24
  super(values.map { |value| BarcodeValidation::Digit.new(value) })
22
25
  end
23
26
 
@@ -28,6 +31,10 @@ module BarcodeValidation
28
31
  end
29
32
  end
30
33
 
34
+ def *(other)
35
+ self.class.new(super)
36
+ end
37
+
31
38
  ArgumentError = Error::ArgumentErrorClass.new(DigitSequence)
32
39
  end
33
40
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "forwardable"
2
4
 
3
5
  module BarcodeValidation
@@ -1 +1,3 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative "error/argument_error_class"
@@ -0,0 +1,102 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "forwardable"
4
+
5
+ module BarcodeValidation
6
+ module GTIN
7
+ class Base < BarcodeValidation::DigitSequence
8
+ MODULUS = 10
9
+
10
+ extend Forwardable
11
+
12
+ attr_reader :input
13
+
14
+ def initialize(input)
15
+ @input = input
16
+
17
+ super
18
+ rescue BarcodeValidation::Error => e
19
+ BarcodeValidation::InvalidGTIN.new(input, error: e)
20
+ end
21
+
22
+ def valid?
23
+ valid_length == length && check_digit.valid?
24
+ end
25
+
26
+ def valid_length
27
+ raise(AbstractMethodError, "Concrete classes must define the VALID_LENGTH constant") unless self.class.const_defined?(:VALID_LENGTH)
28
+
29
+ self.class::VALID_LENGTH
30
+ end
31
+
32
+ class AbstractMethodError < StandardError; end
33
+
34
+ def to_all_valid
35
+ [
36
+ to_gtin_8,
37
+ to_gtin_12,
38
+ to_gtin_13,
39
+ to_gtin_14,
40
+ ].select(&:valid?)
41
+ end
42
+
43
+ def to_gtin_8
44
+ is_a?(GTIN8) ? self : transcode_to(GTIN8)
45
+ end
46
+
47
+ def to_gtin_12
48
+ is_a?(GTIN12) ? self : transcode_to(GTIN12)
49
+ end
50
+
51
+ def to_gtin_13
52
+ is_a?(GTIN13) ? self : transcode_to(GTIN13)
53
+ end
54
+
55
+ def to_gtin_14
56
+ is_a?(GTIN14) ? self : transcode_to(GTIN14)
57
+ end
58
+
59
+ private
60
+
61
+ def check_digit
62
+ CheckDigit.new(last, expected: expected_check_digit)
63
+ end
64
+
65
+ def expected_check_digit
66
+ (MODULUS - weighted_checkable_digit_sum) % MODULUS
67
+ end
68
+
69
+ def weighted_checkable_digit_sum
70
+ checkable_digits
71
+ .zip([3, 1].cycle)
72
+ .map { |digit, factor| digit * factor }
73
+ .reduce(&:+)
74
+ end
75
+
76
+ def checkable_digits
77
+ take(length - 1).reverse.map(&:to_i)
78
+ end
79
+
80
+ # Instantiates the given class with the string value of this instance
81
+ # with any leading zeros stripped out, and then zero-padded up to the
82
+ # valid length of the given class. If the resulting string is <> the
83
+ # valid length of the target format, the returned object will be a
84
+ # BarcodeValidation::InvalidGTIN with valid? = false and a meaningful
85
+ # error message.
86
+ def transcode_to(klass)
87
+ gtin = klass.new(format("%0#{klass::VALID_LENGTH}d", to_s.gsub(/^0+/, "")))
88
+
89
+ if gtin.valid?
90
+ gtin
91
+ else
92
+ BarcodeValidation::InvalidGTIN.new(
93
+ input,
94
+ error: klass::ConversionError.new(klass).exception(input),
95
+ )
96
+ end
97
+ end
98
+
99
+ ConversionError = Error::ArgumentErrorClass.new(self)
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BarcodeValidation
4
+ module GTIN
5
+ class CheckDigit < DelegateClass(Digit)
6
+ include Mixin::ValueObject
7
+
8
+ attr_reader :actual, :expected
9
+
10
+ def initialize(actual, expected: nil)
11
+ expected = actual if expected.nil?
12
+ @expected = Digit.new(expected)
13
+ @actual = Digit.new(actual)
14
+ super(@actual)
15
+ end
16
+
17
+ def valid?
18
+ actual == expected
19
+ end
20
+
21
+ def inspect
22
+ return super if valid?
23
+
24
+ "#<#{self.class}(#{actual}) invalid: expected #{expected}>"
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BarcodeValidation
4
+ module GTIN
5
+ class GTIN12 < BarcodeValidation::GTIN::Base
6
+ VALID_LENGTH = 12
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BarcodeValidation
4
+ module GTIN
5
+ class GTIN13 < BarcodeValidation::GTIN::Base
6
+ VALID_LENGTH = 13
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BarcodeValidation
4
+ module GTIN
5
+ class GTIN14 < BarcodeValidation::GTIN::Base
6
+ VALID_LENGTH = 14
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BarcodeValidation
4
+ module GTIN
5
+ class GTIN8 < BarcodeValidation::GTIN::Base
6
+ VALID_LENGTH = 8
7
+ end
8
+ end
9
+ end
@@ -1,42 +1,27 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "forwardable"
4
+ require_relative "invalid_gtin"
5
+ require_relative "gtin/base"
6
+ require_relative "gtin/check_digit"
7
+ require_relative "gtin/gtin8"
8
+ require_relative "gtin/gtin12"
9
+ require_relative "gtin/gtin13"
10
+ require_relative "gtin/gtin14"
2
11
 
3
12
  module BarcodeValidation
4
- class GTIN < BarcodeValidation::DigitSequence
5
- extend Forwardable
6
- include Mixin::HasCheckDigit
7
-
8
- VALID_LENGTHS = [8, 12, 13, 14].freeze
9
-
10
- def self.new(input)
11
- super
12
- rescue BarcodeValidation::Error => e
13
- return InvalidGTIN.new(input, error: e)
14
- end
15
-
16
- def valid?
17
- VALID_LENGTHS.include?(length) && check_digit.valid?
18
- end
19
-
20
- class CheckDigit < DelegateClass(Digit)
21
- include Adamantium::Flat
22
- include Mixin::ValueObject
23
-
24
- attr_reader :actual, :expected
25
-
26
- def initialize(actual, expected: nil)
27
- expected = actual if expected.nil?
28
- @expected = Digit.new(expected)
29
- @actual = Digit.new(actual)
30
- super(@actual)
13
+ module GTIN
14
+ class << self
15
+ def new(input)
16
+ (class_for_input(input) || BarcodeValidation::InvalidGTIN).new(input)
31
17
  end
32
18
 
33
- def valid?
34
- actual == expected
35
- end
19
+ private
36
20
 
37
- def inspect
38
- return super if valid?
39
- "#<#{self.class}(#{actual}) invalid: expected #{expected}>"
21
+ def class_for_input(input)
22
+ [GTIN8, GTIN12, GTIN13, GTIN14].find do |klass|
23
+ input.to_s.size == klass::VALID_LENGTH
24
+ end
40
25
  end
41
26
  end
42
27
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "delegate"
2
4
 
3
5
  module BarcodeValidation
@@ -17,7 +19,28 @@ module BarcodeValidation
17
19
 
18
20
  def error_message
19
21
  return @error.message if @error.respond_to? :message
22
+
20
23
  @error.inspect
21
24
  end
25
+
26
+ def to_all_valid
27
+ []
28
+ end
29
+
30
+ def to_gtin_8
31
+ self
32
+ end
33
+
34
+ def to_gtin_12
35
+ self
36
+ end
37
+
38
+ def to_gtin_13
39
+ self
40
+ end
41
+
42
+ def to_gtin_14
43
+ self
44
+ end
22
45
  end
23
46
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module BarcodeValidation
2
4
  module Mixin
3
5
  # Wraps #last as a CheckDigit
@@ -1,4 +1,4 @@
1
- require "adamantium"
1
+ # frozen_string_literal: true
2
2
 
3
3
  module BarcodeValidation
4
4
  module Mixin
@@ -8,10 +8,6 @@ module BarcodeValidation
8
8
  end
9
9
 
10
10
  module ClassMethods
11
- # Memoizes return values based on the inputs
12
- def new(*args)
13
- (@__new_cache ||= {})[args] ||= super
14
- end
15
11
  end
16
12
 
17
13
  def eql?(other)
@@ -22,8 +18,8 @@ module BarcodeValidation
22
18
  "#<#{description}>"
23
19
  end
24
20
 
25
- def pretty_print(pp)
26
- pp.text inspect
21
+ def pretty_print(value)
22
+ value.text inspect
27
23
  end
28
24
 
29
25
  private
@@ -1,2 +1,4 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative "mixin/has_check_digit"
2
4
  require_relative "mixin/value_object"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module BarcodeValidation
2
- VERSION = "2.1.0".freeze
4
+ VERSION = "2.4.0"
3
5
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "barcodevalidation/mixin"
2
4
  require "barcodevalidation/error"
3
5
  require "barcodevalidation/digit"
@@ -23,6 +25,7 @@ module BarcodeValidation
23
25
  # Strips punctuation
24
26
  def sanitize(input)
25
27
  return input.gsub(/(\s|[-_])/, "") if input.respond_to? :gsub
28
+
26
29
  input
27
30
  end
28
31
  end
metadata CHANGED
@@ -1,29 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: barcodevalidation
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.0
4
+ version: 2.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Marketplacer
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-04-13 00:00:00.000000000 Z
12
- dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: adamantium
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - ">="
18
- - !ruby/object:Gem::Version
19
- version: '0'
20
- type: :runtime
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - ">="
25
- - !ruby/object:Gem::Version
26
- version: '0'
11
+ date: 2022-02-03 00:00:00.000000000 Z
12
+ dependencies: []
27
13
  description: A RubyGem to parse and validate barcodes
28
14
  email:
29
15
  - it@marketplacer.com
@@ -41,6 +27,12 @@ files:
41
27
  - lib/barcodevalidation/error.rb
42
28
  - lib/barcodevalidation/error/argument_error_class.rb
43
29
  - lib/barcodevalidation/gtin.rb
30
+ - lib/barcodevalidation/gtin/base.rb
31
+ - lib/barcodevalidation/gtin/check_digit.rb
32
+ - lib/barcodevalidation/gtin/gtin12.rb
33
+ - lib/barcodevalidation/gtin/gtin13.rb
34
+ - lib/barcodevalidation/gtin/gtin14.rb
35
+ - lib/barcodevalidation/gtin/gtin8.rb
44
36
  - lib/barcodevalidation/invalid_gtin.rb
45
37
  - lib/barcodevalidation/mixin.rb
46
38
  - lib/barcodevalidation/mixin/has_check_digit.rb
@@ -58,15 +50,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
58
50
  requirements:
59
51
  - - ">="
60
52
  - !ruby/object:Gem::Version
61
- version: '0'
53
+ version: '2.5'
62
54
  required_rubygems_version: !ruby/object:Gem::Requirement
63
55
  requirements:
64
56
  - - ">="
65
57
  - !ruby/object:Gem::Version
66
58
  version: '0'
67
59
  requirements: []
68
- rubyforge_project:
69
- rubygems_version: 2.4.5.1
60
+ rubygems_version: 3.1.4
70
61
  signing_key:
71
62
  specification_version: 4
72
63
  summary: Parses and validates barcodes