gs1 1.1.0 → 2.0.1
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 +4 -4
- data/CHANGELOG.md +54 -10
- data/README.md +67 -5
- data/gs1.gemspec +7 -10
- data/lib/gs1/barcode/attribute_validator.rb +33 -0
- data/lib/gs1/barcode/attribute_validators/ignoring_record_validator.rb +11 -0
- data/lib/gs1/barcode/attribute_validators/record_validator.rb +24 -0
- data/lib/gs1/barcode/base.rb +28 -14
- data/lib/gs1/barcode/definitions.rb +0 -22
- data/lib/gs1/barcode/errors.rb +2 -2
- data/lib/gs1/barcode/healthcare.rb +1 -1
- data/lib/gs1/barcode/segment.rb +6 -3
- data/lib/gs1/barcode/tokenizer.rb +7 -2
- data/lib/gs1/barcode.rb +3 -0
- data/lib/gs1/extensions/date.rb +1 -1
- data/lib/gs1/extensions/date_month_based.rb +1 -1
- data/lib/gs1/generated_ai_classes.rb +3958 -0
- data/lib/gs1/record.rb +3 -0
- data/lib/gs1/syntax_dictionary/parser.rb +223 -0
- data/lib/gs1/syntax_dictionary/specification_parser.rb +74 -0
- data/lib/gs1/version.rb +1 -1
- data/lib/gs1.rb +33 -21
- metadata +12 -116
- data/.gitignore +0 -13
- data/.rspec +0 -3
- data/.rubocop.yml +0 -13
- data/.ruby-gemset +0 -1
- data/.ruby-version +0 -1
- data/.travis.yml +0 -18
- data/Gemfile +0 -6
- data/Rakefile +0 -6
- data/bin/console +0 -14
- data/bin/setup +0 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 80e2897a3ab7721ee0bd9ff82da8336a512ef1e62d456be6cb910324b93d702f
|
4
|
+
data.tar.gz: b40467ed1fa1f6fdb8782c962b0206241d93f6f9e5a1443660dcab69db6d33c8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 82b3a6499e115789293850ed64333b68525c17c941e9eab916fc5653e0f76ed2258eeed17e0db4dc489aa939ddb6a4bf84b830a093bb8a7e5cd124968a22aa21
|
7
|
+
data.tar.gz: c93ee42951979767f2f2dbd1af387fdcdccc20d805e43add35375d17909be4c932f7893ff91c847da2be5db06dab0724caae9850aed21342a0abf151832e2b68
|
data/CHANGELOG.md
CHANGED
@@ -1,15 +1,59 @@
|
|
1
|
-
|
1
|
+
# Changelog
|
2
|
+
All notable changes to this project will be documented in this file.
|
2
3
|
|
3
|
-
|
4
|
-
|
4
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
5
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
5
6
|
|
6
|
-
|
7
|
+
## [Unreleased]
|
7
8
|
|
8
|
-
|
9
|
-
|
9
|
+
## [2.0.1] - 2025-04-23
|
10
|
+
### Fixed
|
11
|
+
- Fix the CI release pipeline
|
10
12
|
|
11
|
-
|
12
|
-
|
13
|
+
## [2.0.0] - 2025-04-22
|
14
|
+
### Changed
|
15
|
+
- Minimum supported version of Ruby is now 3.0.5 (breaking change)
|
13
16
|
|
14
|
-
|
15
|
-
|
17
|
+
- Extra elements in barcodes are now ignored (breaking change). Set the
|
18
|
+
`ignore_extra_barcode_elements` configuration option to `false` to restore
|
19
|
+
previous behavior
|
20
|
+
|
21
|
+
- AI classes are lazy loaded now (possibly breaking change)
|
22
|
+
|
23
|
+
### Added
|
24
|
+
- Add a new option (`ignore_extra_barcode_elements`) to configure if extra
|
25
|
+
elements in barcodes should be reported as an error or ignored. By default,
|
26
|
+
ignore
|
27
|
+
|
28
|
+
- Added the `GS1.ai_classes` method. This contains all AI classes. This is the
|
29
|
+
same as `GS1::AI_CLASSES` from previous versions, buy lazy loaded
|
30
|
+
|
31
|
+
- All application identifiers (as of 2025-01-30) are now recognized
|
32
|
+
|
33
|
+
### Removed
|
34
|
+
- Removed the `GS1::AI_CLASSES` constant. Use `GS1.ai_classes` instead
|
35
|
+
- The following classes have been removed: `GS1::Batch` and `GS1::SerialNumber`.
|
36
|
+
They have been replaced with generated anonymous classes.
|
37
|
+
|
38
|
+
## [1.1.0] - 2021-08-23
|
39
|
+
|
40
|
+
### Added
|
41
|
+
- Adds support to calculating checksum for GSIN
|
42
|
+
|
43
|
+
## [1.0.0] - 2019-08-30
|
44
|
+
|
45
|
+
### Changed
|
46
|
+
- Returns `nil` unless no attribute for barcode segment (breaking change)
|
47
|
+
|
48
|
+
### Added
|
49
|
+
- Add errors to a barcode
|
50
|
+
|
51
|
+
### Fixed
|
52
|
+
- Fix `nil` argument for barcode
|
53
|
+
|
54
|
+
[Unreleased]: https://github.com/apoex/gs1/compare/v2.0.1...HEAD
|
55
|
+
|
56
|
+
[2.0.1]: https://github.com/apoex/gs1/compare/v2.0.0...v2.0.1
|
57
|
+
[2.0.0]: https://github.com/apoex/gs1/compare/v1.1.0...v2.0.0
|
58
|
+
[1.1.0]: https://github.com/apoex/gs1/compare/v1.0.0...v1.1.0
|
59
|
+
[1.0.0]: https://github.com/apoex/gs1/releases/tag/v1.0.0
|
data/README.md
CHANGED
@@ -30,6 +30,7 @@ There are some configuration you can do before start using this lib.
|
|
30
30
|
GS1.configure do |config|
|
31
31
|
config.company_prefix = '123456789'
|
32
32
|
config.barcode_separator = '~' # Default is "\u001E"
|
33
|
+
config.ignore_extra_barcode_elements = false # Default is true
|
33
34
|
end
|
34
35
|
```
|
35
36
|
|
@@ -77,18 +78,79 @@ GS1::Barcode::Healthcare.from_scan("01034531200000111719112510ABCD1234\u001E2110
|
|
77
78
|
|
78
79
|
## Development
|
79
80
|
|
80
|
-
After checking out the repo, run `bin/setup` to install dependencies. Then, run
|
81
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run
|
82
|
+
`rake spec` to run the tests. You can also run `bin/console` for an interactive
|
83
|
+
prompt that will allow you to experiment.
|
81
84
|
|
82
|
-
To install this gem onto your local machine, run `bundle exec rake install`. To
|
85
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To
|
86
|
+
release a new version, update the version number in `version.rb`, and then run
|
87
|
+
`bundle exec rake release`, which will create a git tag for the version, push
|
88
|
+
git commits and tags, and push the `.gem` file to
|
89
|
+
[rubygems.org](https://rubygems.org).
|
90
|
+
|
91
|
+
### Creating a Release
|
92
|
+
|
93
|
+
#### Update the Changelog
|
94
|
+
|
95
|
+
1. Rename the [Unreleased] section to match the version that is being released
|
96
|
+
1. Add the current date in the section from previous step. See existing entries
|
97
|
+
1. Add a new section for the `Unreleased` section at the top
|
98
|
+
1. Add a new reference link for the new section at the bottom of the changelog
|
99
|
+
1. Update the `Unreleased` reference link at the bottom of the changelog
|
100
|
+
|
101
|
+
#### Publish New Version of Gem
|
102
|
+
|
103
|
+
To publish a new version of this gem, follow the steps below:
|
104
|
+
|
105
|
+
1. Update the version in the [version.rb](lib/gs1/version.rb) file
|
106
|
+
1. Run `bundle` to update Gemfile.lock
|
107
|
+
1. Commit and push the changes
|
108
|
+
|
109
|
+
1. Run `rake release:initiate`. This initiates a new release by creating a Git
|
110
|
+
tag with the version specified in [version.rb](lib/gs1/version.rb). It will
|
111
|
+
then push the Git tag. This will trigger a job in the CI pipeline, which
|
112
|
+
will build the gem and publish it to https://rubygems.org. It will also
|
113
|
+
create a GitHub Release, in draft mode
|
114
|
+
|
115
|
+
1. Check the GitHub Release and then publish it
|
83
116
|
|
84
117
|
## Contributing
|
85
118
|
|
86
|
-
Bug reports and pull requests are welcome on GitHub at
|
119
|
+
Bug reports and pull requests are welcome on GitHub at
|
120
|
+
https://github.com/apoex/gs1. This project is intended to be a safe, welcoming
|
121
|
+
space for collaboration, and contributors are expected to adhere to the
|
122
|
+
[Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
123
|
+
|
124
|
+
### Changelog
|
125
|
+
|
126
|
+
The changelog is maintained in the [CHANGELOG.md](CHANGELOG.md) file, following
|
127
|
+
the [Keep a Changelog] format. The changelog is updated incrementally. That is,
|
128
|
+
for every new feature or bugfix, add an entry to the changelog. New entries are
|
129
|
+
added below the [Unreleased] section, with an appropriate sub header.
|
130
|
+
|
131
|
+
### Update Known Application Identifiers
|
132
|
+
|
133
|
+
1. Download the latest version of the [GS1 syntax dictionary](gs1_syntax_dictionary)
|
134
|
+
|
135
|
+
1. Place the syntax dictionary in the
|
136
|
+
[gs1-syntax-dictionary.txt](gs1-syntax-dictionary.txt) file
|
137
|
+
|
138
|
+
1. Run the script to generate the AI classes from the syntax
|
139
|
+
dictionary: [`./bin/generate_ai_classes`](bin/generate_ai_classes)
|
140
|
+
|
141
|
+
1. Commit all changed files
|
87
142
|
|
88
143
|
## License
|
89
144
|
|
90
|
-
The gem is available as open source under the terms of the [MIT
|
145
|
+
The gem is available as open source under the terms of the [MIT
|
146
|
+
License](https://opensource.org/licenses/MIT).
|
91
147
|
|
92
148
|
## Code of Conduct
|
93
149
|
|
94
|
-
Everyone interacting in the Gs1 project’s codebases, issue trackers, chat rooms
|
150
|
+
Everyone interacting in the Gs1 project’s codebases, issue trackers, chat rooms
|
151
|
+
and mailing lists is expected to follow the [code of
|
152
|
+
conduct](https://github.com/apoex/gs1/blob/master/CODE_OF_CONDUCT.md).
|
153
|
+
|
154
|
+
[gs1_syntax_dictionary]: https://ref.gs1.org/tools/gs1-barcode-syntax-resource/syntax-dictionary
|
155
|
+
[Keep a Changelog]: https://keepachangelog.com/en/1.1.0
|
156
|
+
[Unreleased]: https://github.com/apoex/gs1/blob/master/CHANGELOG.md#unreleased
|
data/gs1.gemspec
CHANGED
@@ -19,24 +19,21 @@ Gem::Specification.new do |spec|
|
|
19
19
|
spec.metadata['allowed_push_host'] = 'https://rubygems.org'
|
20
20
|
else
|
21
21
|
raise 'RubyGems 2.0 or newer is required to protect against ' \
|
22
|
-
|
22
|
+
'public gem pushes.'
|
23
23
|
end
|
24
24
|
|
25
25
|
# Specify which files should be added to the gem when it is released.
|
26
26
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
27
27
|
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
28
|
-
`git ls-files -z
|
28
|
+
`git ls-files -z`
|
29
|
+
.split("\x0")
|
30
|
+
.filter { _1.start_with?('lib') } +
|
31
|
+
%w[gs1.gemspec CHANGELOG.md CODE_OF_CONDUCT.md LICENSE.txt README.md]
|
29
32
|
end
|
30
33
|
spec.bindir = 'exe'
|
31
34
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
32
35
|
spec.require_paths = ['lib']
|
33
|
-
spec.required_ruby_version = '>=
|
36
|
+
spec.required_ruby_version = '>= 3.0.5'
|
34
37
|
|
35
|
-
spec.
|
36
|
-
spec.add_development_dependency 'byebug', '~> 10.0'
|
37
|
-
spec.add_development_dependency 'rake', '>= 10.0'
|
38
|
-
spec.add_development_dependency 'rb-readline', '~> 0.1'
|
39
|
-
spec.add_development_dependency 'rspec', '~> 3.0'
|
40
|
-
spec.add_development_dependency 'rubocop', '~> 0.49.0'
|
41
|
-
spec.add_development_dependency 'simplecov', '~> 0.1'
|
38
|
+
spec.metadata['rubygems_mfa_required'] = 'true'
|
42
39
|
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module GS1
|
2
|
+
module Barcode
|
3
|
+
class AttributeValidator
|
4
|
+
def self.for(configuration:)
|
5
|
+
attribute_record_validator = if configuration.ignore_extra_barcode_elements
|
6
|
+
AttributeValidators::IgnoringRecordValidator
|
7
|
+
else
|
8
|
+
AttributeValidators::RecordValidator
|
9
|
+
end
|
10
|
+
|
11
|
+
new(attribute_record_validator: attribute_record_validator.new)
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize(attribute_record_validator: AttributeValidators::IgnoringRecordValidator.new)
|
15
|
+
@attribute_record_validator = attribute_record_validator
|
16
|
+
end
|
17
|
+
|
18
|
+
def validate_data(barcode, attribute_name)
|
19
|
+
return unless barcode.instance_variable_get("@#{attribute_name}")
|
20
|
+
|
21
|
+
barcode.errors[attribute_name] << Error.new(:already_defined, persistent: true)
|
22
|
+
end
|
23
|
+
|
24
|
+
def validate_record(barcode, attribute_name, &block)
|
25
|
+
attribute_record_validator.validate(barcode, attribute_name, &block)
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
attr_reader :attribute_record_validator
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module GS1
|
2
|
+
module Barcode
|
3
|
+
module AttributeValidators
|
4
|
+
class RecordValidator
|
5
|
+
def validate(barcode, attribute_name)
|
6
|
+
barcode.class.records.find { |r| r.underscore_name == attribute_name }.tap do |record|
|
7
|
+
if record
|
8
|
+
yield record
|
9
|
+
next
|
10
|
+
end
|
11
|
+
|
12
|
+
on_error(barcode, attribute_name)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def on_error(barcode, attribute_name)
|
19
|
+
barcode.errors[attribute_name] << Error.new(:unknown_attribute, persistent: true)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/lib/gs1/barcode/base.rb
CHANGED
@@ -5,15 +5,16 @@ module GS1
|
|
5
5
|
class Base
|
6
6
|
include Definitions
|
7
7
|
|
8
|
-
def initialize(options = {})
|
9
|
-
options
|
10
|
-
|
11
|
-
|
12
|
-
|
8
|
+
def initialize(attributes = {}, options = {})
|
9
|
+
attribute_validator = options[:attribute_validator] || AttributeValidator.new
|
10
|
+
attributes.each do |(name, data)|
|
11
|
+
attribute_validator.validate_data(self, name)
|
12
|
+
attribute_validator.validate_record(self, name) do |record|
|
13
|
+
instance_variable_set("@#{name}", record.new(data))
|
13
14
|
end
|
14
15
|
end
|
15
16
|
|
16
|
-
@params_order =
|
17
|
+
@params_order = attributes.to_h.keys
|
17
18
|
end
|
18
19
|
|
19
20
|
def errors
|
@@ -21,20 +22,33 @@ module GS1
|
|
21
22
|
end
|
22
23
|
|
23
24
|
class << self
|
24
|
-
def
|
25
|
-
|
25
|
+
def for(attributes, configuration:)
|
26
|
+
attribute_validator = AttributeValidator.for(configuration: configuration)
|
27
|
+
new(attributes, attribute_validator: attribute_validator)
|
26
28
|
end
|
27
29
|
|
28
|
-
def from_scan(barcode, separator: GS1.configuration.barcode_separator)
|
29
|
-
|
30
|
+
def from_scan!(barcode, separator: GS1.configuration.barcode_separator, ai_classes: GS1.ai_classes)
|
31
|
+
self.for(
|
32
|
+
scan_to_params!(barcode, separator: separator, ai_classes: ai_classes),
|
33
|
+
configuration: GS1.configuration
|
34
|
+
)
|
30
35
|
end
|
31
36
|
|
32
|
-
def
|
33
|
-
|
37
|
+
def from_scan(barcode, separator: GS1.configuration.barcode_separator, ai_classes: GS1.ai_classes)
|
38
|
+
self.for(
|
39
|
+
scan_to_params(barcode, separator: separator, ai_classes: ai_classes),
|
40
|
+
configuration: GS1.configuration
|
41
|
+
)
|
34
42
|
end
|
35
43
|
|
36
|
-
def scan_to_params(barcode, separator: GS1.configuration.barcode_separator)
|
37
|
-
Tokenizer.new(barcode, separator: separator)
|
44
|
+
def scan_to_params!(barcode, separator: GS1.configuration.barcode_separator, ai_classes: GS1.ai_classes)
|
45
|
+
Tokenizer.new(barcode, separator: separator, ai_classes: ai_classes)
|
46
|
+
.to_params!
|
47
|
+
end
|
48
|
+
|
49
|
+
def scan_to_params(barcode, separator: GS1.configuration.barcode_separator, ai_classes: GS1.ai_classes)
|
50
|
+
Tokenizer.new(barcode, separator: separator, ai_classes: ai_classes)
|
51
|
+
.to_params
|
38
52
|
end
|
39
53
|
end
|
40
54
|
end
|
@@ -5,7 +5,6 @@ module GS1
|
|
5
5
|
module Definitions
|
6
6
|
def self.included(base)
|
7
7
|
base.extend ClassMethods
|
8
|
-
base.send :include, InstanceMethods
|
9
8
|
end
|
10
9
|
|
11
10
|
# Adding defintion class methods.
|
@@ -22,27 +21,6 @@ module GS1
|
|
22
21
|
end
|
23
22
|
end
|
24
23
|
end
|
25
|
-
|
26
|
-
# Adding defintion instance methods.
|
27
|
-
#
|
28
|
-
module InstanceMethods
|
29
|
-
def validate_attribute_data(attribute_name)
|
30
|
-
return unless instance_variable_get("@#{attribute_name}")
|
31
|
-
|
32
|
-
errors[attribute_name] << Error.new(:already_defined, persistent: true)
|
33
|
-
end
|
34
|
-
|
35
|
-
def validate_attribute_record(attribute_name)
|
36
|
-
self.class.records.find { |r| r.underscore_name == attribute_name }.tap do |record|
|
37
|
-
if record
|
38
|
-
yield record
|
39
|
-
next
|
40
|
-
end
|
41
|
-
|
42
|
-
errors[attribute_name] << Error.new(:unknown_attribute, persistent: true)
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
24
|
end
|
47
25
|
end
|
48
26
|
end
|
data/lib/gs1/barcode/errors.rb
CHANGED
data/lib/gs1/barcode/segment.rb
CHANGED
@@ -5,9 +5,10 @@ module GS1
|
|
5
5
|
class Segment
|
6
6
|
attr_reader :data, :separator
|
7
7
|
|
8
|
-
def initialize(data, separator: GS1.configuration.barcode_separator)
|
8
|
+
def initialize(data, separator: GS1.configuration.barcode_separator, ai_classes: GS1.ai_classes)
|
9
9
|
@data = data.to_s.chars
|
10
10
|
@separator = separator
|
11
|
+
@ai_classes = ai_classes
|
11
12
|
end
|
12
13
|
|
13
14
|
def to_params
|
@@ -66,6 +67,8 @@ module GS1
|
|
66
67
|
|
67
68
|
private
|
68
69
|
|
70
|
+
attr_reader :ai_classes
|
71
|
+
|
69
72
|
def ai_variants
|
70
73
|
@ai_variants ||= []
|
71
74
|
end
|
@@ -73,9 +76,9 @@ module GS1
|
|
73
76
|
def process_ai_variants(shifts)
|
74
77
|
return unless can_shift_ai_data?(shifts)
|
75
78
|
|
76
|
-
ai_variants << ai_variants.last.to_s + data.shift(shifts).join
|
79
|
+
ai_variants << (ai_variants.last.to_s + data.shift(shifts).join)
|
77
80
|
|
78
|
-
|
81
|
+
ai_classes[ai_variants.last]
|
79
82
|
end
|
80
83
|
|
81
84
|
def can_shift_ai_data?(shifts)
|
@@ -6,10 +6,11 @@ module GS1
|
|
6
6
|
class Tokenizer
|
7
7
|
attr_reader :data, :separator, :params
|
8
8
|
|
9
|
-
def initialize(data, separator: GS1.configuration.barcode_separator)
|
9
|
+
def initialize(data, separator: GS1.configuration.barcode_separator, ai_classes: GS1.ai_classes)
|
10
10
|
@data = data
|
11
11
|
@separator = separator
|
12
12
|
@params = []
|
13
|
+
@ai_classes = ai_classes
|
13
14
|
end
|
14
15
|
|
15
16
|
def to_params
|
@@ -22,7 +23,11 @@ module GS1
|
|
22
23
|
|
23
24
|
private
|
24
25
|
|
26
|
+
attr_reader :ai_classes
|
27
|
+
|
28
|
+
# rubocop:disable Style/OptionalBooleanParameter
|
25
29
|
def segment_to_params(input, bang = false)
|
30
|
+
# rubocop:enable Style/OptionalBooleanParameter
|
26
31
|
segment_from_input(input, bang) do |segment|
|
27
32
|
next if segment.to_params.empty?
|
28
33
|
|
@@ -37,7 +42,7 @@ module GS1
|
|
37
42
|
end
|
38
43
|
|
39
44
|
def segment_from_input(input, bang)
|
40
|
-
Segment.new(input, separator: separator).tap do |segment|
|
45
|
+
Segment.new(input, separator: separator, ai_classes: ai_classes).tap do |segment|
|
41
46
|
segment.validate! if bang
|
42
47
|
yield segment if block_given?
|
43
48
|
end
|
data/lib/gs1/barcode.rb
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
+
require 'gs1/barcode/attribute_validator'
|
2
|
+
require 'gs1/barcode/attribute_validators/record_validator'
|
3
|
+
require 'gs1/barcode/attribute_validators/ignoring_record_validator'
|
1
4
|
require 'gs1/barcode/definitions'
|
2
5
|
require 'gs1/barcode/error'
|
3
6
|
require 'gs1/barcode/errors'
|
data/lib/gs1/extensions/date.rb
CHANGED