barcodevalidation 2.2.0 → 2.3.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2783879bb9ef02f2f9e35dbb44141f4c21de2d6bebfb6b3643806a18eec2f13f
4
- data.tar.gz: 0d839d223853a598a05434a401dd0282ea2f48713ab27ea99bf4043bdda68e77
3
+ metadata.gz: d0ddfbb1e0066701228173d80f24f18eca5bf195e4cb0ba84d1a2b7cff1f306b
4
+ data.tar.gz: 21fd5a0a5eb2876b5b764c49d0ae2a4130a2cd4710e0ee3784b56221f5d0c895
5
5
  SHA512:
6
- metadata.gz: 252f2f26e2787311a8772b2513c017de0c7c9ad0d5acec5e52fbf6ab859781df4fdb30da4b477a942d42ec8997408a5193ba9ffbf7c42800c8d04f5bd5713f6c
7
- data.tar.gz: 55ee58d3b10b39756e384d00e9eb3c3b2950b28572fcdd264e203639a936a92aea5523d636b0513ef329b273c45f015e21fefea4eb1b26cd3a53b5b9370b453e
6
+ metadata.gz: eac5d8884e82da6c0f57b1042887d8337a6f1bebb91062b068919f42513e90a869edfd048389fd4529a08537a326a582dcd9d0110e327d8dd1726cd93eebb0fb
7
+ data.tar.gz: 8448952e7fa2e83336f67de3af3b6b1f3cee49d57ed180df5402c4d9b85136fa332ee345b4c4a8c024be909d709125e29d7ca42c0df228e4a5013b0d4c6e4d4c
@@ -1,8 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  lib = File.expand_path("lib", __dir__)
2
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
5
  require "barcodevalidation/version"
4
6
 
5
7
  Gem::Specification.new do |spec|
8
+ spec.required_ruby_version = "~> 2.5"
6
9
  spec.name = "barcodevalidation"
7
10
  spec.version = BarcodeValidation::VERSION
8
11
  spec.authors = ["Marketplacer"]
@@ -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,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
@@ -1,4 +1,7 @@
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)
@@ -10,6 +13,7 @@ module BarcodeValidation
10
13
  def initialize(input)
11
14
  value = Integer(input)
12
15
  raise ::ArgumentError unless (0..9).cover? value
16
+
13
17
  super(value)
14
18
  rescue *INTEGER_CAST_ERRORS
15
19
  raise Digit::ArgumentError, input
@@ -1,4 +1,7 @@
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
@@ -18,6 +21,7 @@ module BarcodeValidation
18
21
  def initialize(values)
19
22
  values = cast(values)
20
23
  raise ArgumentError, values unless values.respond_to? :map
24
+
21
25
  super(values.map { |value| BarcodeValidation::Digit.new(value) })
22
26
  end
23
27
 
@@ -1 +1,3 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative "error/argument_error_class"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "forwardable"
2
4
 
3
5
  module BarcodeValidation
@@ -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
- 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
@@ -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,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BarcodeValidation
4
+ module GTIN
5
+ class CheckDigit < DelegateClass(Digit)
6
+ include Adamantium::Flat
7
+ include Mixin::ValueObject
8
+
9
+ attr_reader :actual, :expected
10
+
11
+ def initialize(actual, expected: nil)
12
+ expected = actual if expected.nil?
13
+ @expected = Digit.new(expected)
14
+ @actual = Digit.new(actual)
15
+ super(@actual)
16
+ end
17
+
18
+ def valid?
19
+ actual == expected
20
+ end
21
+
22
+ def inspect
23
+ return super if valid?
24
+
25
+ "#<#{self.class}(#{actual}) invalid: expected #{expected}>"
26
+ end
27
+ end
28
+ end
29
+ 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,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "delegate"
2
4
 
3
5
  module BarcodeValidation
@@ -17,6 +19,7 @@ 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
22
25
  end
@@ -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
4
  module Mixin
3
5
  # Wraps #last as a CheckDigit
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "adamantium"
2
4
 
3
5
  module BarcodeValidation
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module BarcodeValidation
2
- VERSION = "2.2.0".freeze
4
+ VERSION = "2.3.0"
3
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: barcodevalidation
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.0
4
+ version: 2.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Marketplacer
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-08-28 00:00:00.000000000 Z
11
+ date: 2020-10-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: adamantium
@@ -41,6 +41,12 @@ files:
41
41
  - lib/barcodevalidation/error.rb
42
42
  - lib/barcodevalidation/error/argument_error_class.rb
43
43
  - lib/barcodevalidation/gtin.rb
44
+ - lib/barcodevalidation/gtin/base.rb
45
+ - lib/barcodevalidation/gtin/check_digit.rb
46
+ - lib/barcodevalidation/gtin/gtin12.rb
47
+ - lib/barcodevalidation/gtin/gtin13.rb
48
+ - lib/barcodevalidation/gtin/gtin14.rb
49
+ - lib/barcodevalidation/gtin/gtin8.rb
44
50
  - lib/barcodevalidation/invalid_gtin.rb
45
51
  - lib/barcodevalidation/mixin.rb
46
52
  - lib/barcodevalidation/mixin/has_check_digit.rb
@@ -50,24 +56,24 @@ homepage: https://github.com/marketplacer/barcodevalidation
50
56
  licenses:
51
57
  - MIT
52
58
  metadata: {}
53
- post_install_message:
59
+ post_install_message:
54
60
  rdoc_options: []
55
61
  require_paths:
56
62
  - lib
57
63
  required_ruby_version: !ruby/object:Gem::Requirement
58
64
  requirements:
59
- - - ">="
65
+ - - "~>"
60
66
  - !ruby/object:Gem::Version
61
- version: '0'
67
+ version: '2.5'
62
68
  required_rubygems_version: !ruby/object:Gem::Requirement
63
69
  requirements:
64
70
  - - ">="
65
71
  - !ruby/object:Gem::Version
66
72
  version: '0'
67
73
  requirements: []
68
- rubyforge_project:
69
- rubygems_version: 2.7.6
70
- signing_key:
74
+ rubyforge_project:
75
+ rubygems_version: 2.7.6.2
76
+ signing_key:
71
77
  specification_version: 4
72
78
  summary: Parses and validates barcodes
73
79
  test_files: []