barcodevalidation 2.4.0 → 2.6.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
2
  SHA256:
3
- metadata.gz: 6aa7aea902c16d451d7a53b8b69979013f1b8d438165cf8f4c3c3940be359047
4
- data.tar.gz: ea0ca124f7e9e5cdf919c791747f3663215ab33f073140832a88e936a6f11a9b
3
+ metadata.gz: ba3b5afd4aee1020e30233ec636f17390d4ce3b0683f485e26811d84afe9e7e5
4
+ data.tar.gz: 1c533193d00fad326a78342876b42f15b5a4534d0cd4c47451962687c2dce95e
5
5
  SHA512:
6
- metadata.gz: cbc4e8901c64e54995f4f62dec98e3711a386b88dd693bacc571e22ea4f3e7ae48a6910a75c562456b8e7c788a65a18b1c571395c34a129f3a4da9844e9782a6
7
- data.tar.gz: ee148eacfcae331bbcc83fa454ed564024668145e3580d01f21cc21622d976bd2f9ac17872c69b7eb63050e040edd7fb69223f640ec3407aeea59abb3f4d0a64
6
+ metadata.gz: f295608b02b3ce172d58b45572db6f1c0d566d55fa9277b59c1ba34098503d1bc9513cbb00c785169ff342a242c29c5398771bc578d23ce348c69984c90e84fe
7
+ data.tar.gz: 5784a212986f8973bd2e7d5bcfc473c0b61c9c92c194d966f554e86dedbf92943cf7766a89debe4ee0428967ab6e138b87b8b309a79c85b0fbdcc3b766ae31ac
data/README.md CHANGED
@@ -63,6 +63,46 @@ bad.to_all_valid # => []
63
63
  ```
64
64
 
65
65
 
66
+ Custom GTINs
67
+ ------------
68
+
69
+ If the standard GTINs provided are not enough for your needs, you can implement your own by subclassing `BarcodeValidation::GTIN::Base` or any of its subclasses. If your custom class overlaps with a default class or one of your other custom classes, you can declare `prioritize_before <other class>` to re-order their evaluation order.
70
+
71
+ An example:
72
+
73
+ ```ruby
74
+ # A custom class that handles any length GTIN as long as it starts with "123".
75
+ # Note that we must still provide a VALID_LENGTH to allow transcoding to other GTINs by zero-padding.
76
+ # Due to this inheriting from Base, it is automatically registered and added to the end of the list of classes to check if it `handles?` an input.
77
+ class MyCustomGTIN < BarcodeValidation::GTIN::Base
78
+ VALID_LENGTH = 20
79
+
80
+ def self.handles?(input)
81
+ input.start_with?("123") && input.length <= VALID_LENGTH
82
+ end
83
+
84
+ # Custom validity check
85
+ def valid?
86
+ self.class.handles?(input) && check_digit.valid?
87
+ end
88
+ end
89
+
90
+ # A custom implementation of GTIN13, which addresses a subset of the GTIN13 range.
91
+ class MyCustomGTIN13 < BarcodeValidation::GTIN::GTIN13
92
+ # Ensure we get a chance to handle GTINs before our parent,
93
+ # so we can handle the subset we care about and have our parent handle the rest.
94
+ prioritize_before BarcodeValidation::GTIN::GTIN13
95
+
96
+ def self.handles?(input)
97
+ input.start_with?("123") && super
98
+ end
99
+
100
+ def valid?
101
+ input.start_with?("123") && super
102
+ end
103
+ end
104
+ ```
105
+
66
106
 
67
107
  Development
68
108
  -----------
@@ -19,6 +19,34 @@ module BarcodeValidation
19
19
  BarcodeValidation::InvalidGTIN.new(input, error: e)
20
20
  end
21
21
 
22
+ # Does this class (potentially) handle a GTIN that matches the input?
23
+ # Subclasses can choose to implement their own logic. The default is to look at +VALID_LENGTH+ and use that to match the length of the input the class handles.
24
+ def self.handles?(input)
25
+ return false unless const_defined?(:VALID_LENGTH)
26
+
27
+ input.length == self::VALID_LENGTH
28
+ end
29
+
30
+ # Upon inheritance, register the subclass so users of the library can dynamically add more GTINs in their own code.
31
+ def self.inherited(subclass)
32
+ BarcodeValidation::GTIN.append_gtin_class(subclass)
33
+ end
34
+
35
+ # Ensure this class is earlier in the GTIN classes list than +other_gtin_class+ and thus will get asked earlier if it handles a GTIN.
36
+ def self.prioritize_before(other_gtin_class)
37
+ raise ArgumentError, "The class you want to prioritize before is not a registered prioritized GTIN class." unless GTIN.gtin_class?(other_gtin_class)
38
+
39
+ GTIN.reprioritize_before(self, other_gtin_class)
40
+ end
41
+
42
+ # This class is abstract and should not be included in the list of GTIN classes that actually implement a GTIN.
43
+ def self.abstract_class
44
+ BarcodeValidation::GTIN.remove_gtin_class(self)
45
+ end
46
+
47
+ # GTIN::Base is an abstract class. See GTIN8/12/13/14 for implementations of actual GTINs.
48
+ abstract_class
49
+
22
50
  def valid?
23
51
  valid_length == length && check_digit.valid?
24
52
  end
@@ -56,12 +84,12 @@ module BarcodeValidation
56
84
  is_a?(GTIN14) ? self : transcode_to(GTIN14)
57
85
  end
58
86
 
59
- private
60
-
61
87
  def check_digit
62
88
  CheckDigit.new(last, expected: expected_check_digit)
63
89
  end
64
90
 
91
+ private
92
+
65
93
  def expected_check_digit
66
94
  (MODULUS - weighted_checkable_digit_sum) % MODULUS
67
95
  end
@@ -2,27 +2,62 @@
2
2
 
3
3
  require "forwardable"
4
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"
11
5
 
12
6
  module BarcodeValidation
7
+ # GTIN is responsible for wrapping input in an appropriate GTIN::Base sub-class.
8
+ # An important part of this involves managing the prioritized list of GTIN classes we use for handling input.
9
+ # The methods implemented here are used by GTIN::Base to manage this list and prioritize classes.
13
10
  module GTIN
14
11
  class << self
15
12
  def new(input)
16
13
  (class_for_input(input) || BarcodeValidation::InvalidGTIN).new(input)
17
14
  end
18
15
 
16
+ # Adds the provided class to the back of the list of prioritized GTIN classes.
17
+ def append_gtin_class(gtin_class)
18
+ prioritized_gtin_classes.push(gtin_class) unless gtin_class?(gtin_class)
19
+ nil
20
+ end
21
+
22
+ # Ensure the provided class is removed from the list of prioritized GTIN classes.
23
+ def remove_gtin_class(gtin_class)
24
+ prioritized_gtin_classes.delete(gtin_class)
25
+ nil
26
+ end
27
+
28
+ # Is this a registered prioritized GTIN class?
29
+ # @return [true, false]
30
+ def gtin_class?(gtin_class)
31
+ prioritized_gtin_classes.include?(gtin_class)
32
+ end
33
+
34
+ # @param [Class] high_priority_class The higher priority GTIN class you want to move before the low priority class
35
+ # @param [Class] low_priority_class The low priority GTIN class that the high priority one is moved before
36
+ def reprioritize_before(high_priority_class, low_priority_class)
37
+ low_priority_index = prioritized_gtin_classes.index(low_priority_class)
38
+ remove_gtin_class(high_priority_class)
39
+ prioritized_gtin_classes.insert(low_priority_index, high_priority_class)
40
+ nil
41
+ end
42
+
19
43
  private
20
44
 
45
+ def prioritized_gtin_classes
46
+ @prioritized_gtin_classes ||= []
47
+ end
48
+
21
49
  def class_for_input(input)
22
- [GTIN8, GTIN12, GTIN13, GTIN14].find do |klass|
23
- input.to_s.size == klass::VALID_LENGTH
24
- end
50
+ input = input.to_s.freeze
51
+ prioritized_gtin_classes.find { |klass| klass.handles?(input) }
25
52
  end
26
53
  end
27
54
  end
28
55
  end
56
+
57
+ # Load GTIN implementations after we have our registration setup
58
+ require_relative "gtin/base"
59
+ require_relative "gtin/check_digit"
60
+ require_relative "gtin/gtin8"
61
+ require_relative "gtin/gtin12"
62
+ require_relative "gtin/gtin13"
63
+ require_relative "gtin/gtin14"
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module BarcodeValidation
4
- VERSION = "2.4.0"
4
+ VERSION = "2.6.0"
5
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.4.0
4
+ version: 2.6.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: 2022-02-03 00:00:00.000000000 Z
11
+ date: 2022-09-29 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: A RubyGem to parse and validate barcodes
14
14
  email:
@@ -42,7 +42,7 @@ homepage: https://github.com/marketplacer/barcodevalidation
42
42
  licenses:
43
43
  - MIT
44
44
  metadata: {}
45
- post_install_message:
45
+ post_install_message:
46
46
  rdoc_options: []
47
47
  require_paths:
48
48
  - lib
@@ -57,8 +57,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
57
57
  - !ruby/object:Gem::Version
58
58
  version: '0'
59
59
  requirements: []
60
- rubygems_version: 3.1.4
61
- signing_key:
60
+ rubygems_version: 3.2.33
61
+ signing_key:
62
62
  specification_version: 4
63
63
  summary: Parses and validates barcodes
64
64
  test_files: []