barcodevalidation 2.2.0 → 2.3.1

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
2
  SHA256:
3
- metadata.gz: 2783879bb9ef02f2f9e35dbb44141f4c21de2d6bebfb6b3643806a18eec2f13f
4
- data.tar.gz: 0d839d223853a598a05434a401dd0282ea2f48713ab27ea99bf4043bdda68e77
3
+ metadata.gz: 69f00057d24894273af1d7404d7152f18067b861c8c0a9c553995cc442328768
4
+ data.tar.gz: 30864684c4ea4a27b44907ba99ba9325109344ff257cb2da3bdd10055a5d0ead
5
5
  SHA512:
6
- metadata.gz: 252f2f26e2787311a8772b2513c017de0c7c9ad0d5acec5e52fbf6ab859781df4fdb30da4b477a942d42ec8997408a5193ba9ffbf7c42800c8d04f5bd5713f6c
7
- data.tar.gz: 55ee58d3b10b39756e384d00e9eb3c3b2950b28572fcdd264e203639a936a92aea5523d636b0513ef329b273c45f015e21fefea4eb1b26cd3a53b5b9370b453e
6
+ metadata.gz: d81de8495506f006796a5f40db56b365faf3df44859f954eba74dda4ec17dd18bd86c5f9b51e9e4205b845d1593be82e50f61245e0151b9d52cff9f2e4b5fd6a
7
+ data.tar.gz: 46ca1e1ea7522c114501e8d72c9cbc70eaabae4886d50885a6f620abf0bb28a9ce6f982f9177b0c324fd9aa418b7d0f6558a4923e9eb51e801a350910ee9fc0b
data/README.md CHANGED
@@ -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
 
@@ -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,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,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.1"
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.1
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-11-05 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: []