Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support custom GTINs #29

Merged
merged 7 commits into from
Sep 28, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Support custom GTINs
This refactors GTIN handler class lookup so it can be extended without
monkeypatching. Developers can add/remove classes in
`BarcodeValidation::GTIN.gtin_classes` to control which class wraps a
GTIN. The use case I need this for is internall dummy GTINs that are
longer than any of the standard ones.

The Readme is updated to describe the feature.
  • Loading branch information
Narnach committed Jun 23, 2022
commit a0d0e9b1cab7ce883281102ad15f8e0d76b6b8d1
26 changes: 26 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,32 @@ bad.to_all_valid # => []
```


Custom GTINs
------------

If the standard GTINs provided are not enough for your needs, you can implement your own and register it.
`BarcodeValidation::GTIN.gtin_classes` contains the ordered list of GTIN classes that are checked if they `handle?(input)`.
Add your own class to the list, or remove default ones, to tailor it to your needs. For example:

```ruby
# A custom class that handles any length GTIN as long as it starts with "123".
# Note that we must still provide a VALID_LENGTH to allow transcoding to other GTINs by zero-padding.
class MyCustomGTIN < BarcodeValidation::GTIN::Base
VALID_LENGTH = 20

def self.handles?(input)
input.start_with?("123") && input.length <= VALID_LENGTH
end

# Custom validity check
def valid?
self.class.handles?(input) && check_digit.valid?
end
end

BarcodeValidation::GTIN.gtin_classes.unshift MyCustomGTIN
```


Development
-----------
Expand Down
8 changes: 5 additions & 3 deletions lib/barcodevalidation/gtin.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,19 @@
module BarcodeValidation
module GTIN
class << self
attr_accessor :gtin_classes

def new(input)
(class_for_input(input) || BarcodeValidation::InvalidGTIN).new(input)
end

private

def class_for_input(input)
[GTIN8, GTIN12, GTIN13, GTIN14].find do |klass|
input.to_s.size == klass::VALID_LENGTH
end
input = input.to_s.freeze
gtin_classes.find { |klass| klass.handles?(input) }
end
end
self.gtin_classes = [GTIN8, GTIN12, GTIN13, GTIN14]
end
end
8 changes: 8 additions & 0 deletions lib/barcodevalidation/gtin/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@ def initialize(input)
BarcodeValidation::InvalidGTIN.new(input, error: e)
end

# Does this class (potentially) handle a GTIN that matches the input?
# 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.
def self.handles?(input)
return false unless self.const_defined?(:VALID_LENGTH)

input.length == self::VALID_LENGTH
end

def valid?
valid_length == length && check_digit.valid?
end
Expand Down