barcodevalidation 2.1.0 → 2.4.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
- 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