barcodevalidation 2.5.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: f1472674218493f67abaf42f2c94c4009ca1aabb07180cee0bfd9ef3c6c2fed5
4
- data.tar.gz: f8aa280b1ca3ad091d13c4a1391d7598b82cbcd5db3d9a3c92c65cdb4ce2407b
3
+ metadata.gz: ba3b5afd4aee1020e30233ec636f17390d4ce3b0683f485e26811d84afe9e7e5
4
+ data.tar.gz: 1c533193d00fad326a78342876b42f15b5a4534d0cd4c47451962687c2dce95e
5
5
  SHA512:
6
- metadata.gz: 87096371c819a9efa4f2493edf47ae2d21cccb16922e9b1661aa11de5fcf82aab7a2031ba8ec2660d6026003f905488c793d996c65bc21ab3e0fd44255e672f4
7
- data.tar.gz: 7eaebe15a7d9ff6c8922b46ec6c1cea2b392235c5b2d245038456ae10c3e72618c5b20c465f1f13094cda06fae3aa123dd3c1fdd189c8f717e9fa04875c6c390
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
@@ -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.5.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.5.0
4
+ version: 2.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Marketplacer
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-08-30 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: