edifact_rails 1.2.1 → 2.1.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 +4 -4
- data/CHANGELOG.md +31 -9
- data/README.md +92 -11
- data/lib/edifact_rails/exceptions.rb +9 -0
- data/lib/edifact_rails/formats.rb +9 -0
- data/lib/edifact_rails/parser.rb +116 -62
- data/lib/edifact_rails/serializer.rb +56 -0
- data/lib/edifact_rails/version.rb +1 -1
- data/lib/edifact_rails.rb +11 -3
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 617b14ce31edcecdb4d3c4a599f79612716680513a740a425f2bcd0cdb8f1d65
|
4
|
+
data.tar.gz: aa8d78ea8759f43a1465e2036c55ea704c1dce3f4c67c30f943324d32525787c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a7531b90d3f9d84223e3176fd6ebd012a26076d3f029e30c344c2ab2a26964c069e8a387f5c73c02445cccbc140e3bdba81bbb832ac08c07af7625bc56a4f686
|
7
|
+
data.tar.gz: ccd019d6bd9beac78be1c07563357a4b6f616bdb538e9a66b5b816a2a6ceadcd7abb05749940a8bf6277cc2d9507da0a003e6f8954fa0d90ef6588ade5327f71
|
data/CHANGELOG.md
CHANGED
@@ -1,23 +1,45 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
-
## 1.0
|
3
|
+
## 2.1.0 (18/06/2024)
|
4
4
|
|
5
|
-
*
|
5
|
+
* Added EDIFACT serialization. Contributed by [sallesma](https://github.com/sallesma)
|
6
6
|
|
7
|
-
##
|
7
|
+
## 2.0.0 (18/06/2024)
|
8
8
|
|
9
|
-
* Added support for
|
9
|
+
* Added support for ANSIX12 format.
|
10
10
|
|
11
|
-
|
11
|
+
##### Breaking changes:
|
12
|
+
* `#una_special_characters` renamed to `#special_characters` (since it can now accept input of any supported format)
|
13
|
+
* New `UnrecognizedFormat` Error will now be thrown if the format of the input can not be detected.
|
14
|
+
* In essence, input must begin now with `UNA` or `UNB` (EDIFACT), `STX` (TRADACOMS), or `ISA` (ANSIX12)
|
12
15
|
|
13
|
-
|
16
|
+
## 1.2.1 (4/06/2024)
|
17
|
+
|
18
|
+
* `#una_special_characters` method now also returns decimal notation character, default `.`.
|
19
|
+
* `#una_special_characters` method can now take no arguments, and will return the default special characters if so.
|
14
20
|
|
15
21
|
## 1.2.0 (31/05/2024)
|
16
22
|
|
17
23
|
* Added support for UNA segments. Special characters different from the defaults can now be used.
|
18
24
|
* Added `#una_special_characters` method that returns just the special characters.
|
19
25
|
|
20
|
-
## 1.
|
26
|
+
## 1.1.1 (4/05/2023)
|
27
|
+
|
28
|
+
* Fixed crash caused by running the gem in a production environment.
|
29
|
+
|
30
|
+
## 1.1.0 (27/04/2023)
|
31
|
+
|
32
|
+
* Added support for TRADACOMS input
|
33
|
+
|
34
|
+
## 1.0.0 (26/04/2023)
|
35
|
+
|
36
|
+
* Initial release
|
37
|
+
|
38
|
+
|
39
|
+
|
40
|
+
|
41
|
+
|
42
|
+
|
43
|
+
|
44
|
+
|
21
45
|
|
22
|
-
* `#una_special_characters` method now also returns decimal notation character, default `.`.
|
23
|
-
* `#una_special_characters` method can now take no arguments, and will return the default special characters if so.
|
data/README.md
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
# EdifactRails
|
2
2
|
|
3
|
-
This gem parses EDIFACT or
|
3
|
+
This gem parses EDIFACT, TRADACOMS, or ANSIX12 input, and converts it into a ruby array structure for whatever further processing or validation you desire.
|
4
4
|
|
5
|
-
|
5
|
+
This gem can also take a ruby array input, and serialize it into EDIFACT.
|
6
6
|
|
7
|
-
This gem is heavily inspired by
|
7
|
+
This gem is heavily inspired by [edifact_parser](https://github.com/pvdvreede/edifact_parser)
|
8
8
|
|
9
9
|
## Requirements
|
10
10
|
|
@@ -20,7 +20,7 @@ This gem has been tested on the following ruby versions:
|
|
20
20
|
In your `Gemfile`:
|
21
21
|
|
22
22
|
```ruby
|
23
|
-
gem 'edifact_rails', '~> 1.
|
23
|
+
gem 'edifact_rails', '~> 2.1.0'
|
24
24
|
```
|
25
25
|
|
26
26
|
Otherwise:
|
@@ -36,21 +36,40 @@ If you don't have the gem in your `Gemfile`, you will need to:
|
|
36
36
|
```ruby
|
37
37
|
require 'edifact_rails'
|
38
38
|
```
|
39
|
+
### Parsing
|
39
40
|
|
40
|
-
You can
|
41
|
+
You can parse a string input with `#parse`, or a file with `#parse_file`
|
42
|
+
|
43
|
+
```ruby
|
44
|
+
ruby_array = EdifactRails.parse("UNB+UNOA:3+TESTPLACE:1+DEP1:1+20051107:1159+6002'")
|
45
|
+
```
|
41
46
|
|
42
47
|
```ruby
|
43
48
|
ruby_array = EdifactRails.parse_file("your/file/path")
|
44
49
|
```
|
45
50
|
|
51
|
+
### Serialization
|
52
|
+
|
53
|
+
You can convert a ruby input into EDIFACT with `#serialize`. Use the `with_service` option to insert the UNA segment.
|
54
|
+
|
46
55
|
```ruby
|
47
|
-
|
56
|
+
edifact_output = Edifact.serialize(
|
57
|
+
[
|
58
|
+
["LIN", [1], [1], ["0764569104", "IB"]],
|
59
|
+
["QTY", [1, 25]]
|
60
|
+
],
|
61
|
+
with_service: true
|
62
|
+
)
|
63
|
+
# edifact_output =>
|
64
|
+
"UNA:+.? 'LIN+1+1+0764569104:IB'QTY+1:25'"
|
48
65
|
```
|
49
66
|
|
50
|
-
|
67
|
+
### Special Characters
|
68
|
+
|
69
|
+
You can return the special characters of your input with `#special_characters`.
|
51
70
|
```ruby
|
52
|
-
|
53
|
-
#
|
71
|
+
special_characters = EdifactRails.special_characters(example_edifact_input)
|
72
|
+
# special_characters =>
|
54
73
|
{
|
55
74
|
component_data_element_seperator: ":",
|
56
75
|
data_element_seperator: "+",
|
@@ -60,7 +79,7 @@ una_special_characters = EdifactRails.una_special_characters(your_string_input)
|
|
60
79
|
}
|
61
80
|
```
|
62
81
|
|
63
|
-
## Output
|
82
|
+
## Parse Output
|
64
83
|
|
65
84
|
### EDIFACT
|
66
85
|
|
@@ -179,4 +198,66 @@ Will be returned as:
|
|
179
198
|
['MTR', [3]],
|
180
199
|
['END', [5]]
|
181
200
|
]
|
182
|
-
```
|
201
|
+
```
|
202
|
+
|
203
|
+
### ANSIX12
|
204
|
+
|
205
|
+
This ANSIX12 file:
|
206
|
+
|
207
|
+
```
|
208
|
+
ISA*00* *00* *01*SENDER *01*RECEIVER *231014*1200*U*00401*000000001*1*P*>~
|
209
|
+
GS*SS*APP SENDER*APP RECEIVER*20231014*1200*0001*X*004010~
|
210
|
+
ST*862*0001~
|
211
|
+
BSS*05*12345*20230414*DL*20231014*20231203****ORDER1*A~
|
212
|
+
N1*MI*SEEBURGER AG*ZZ*00000085~
|
213
|
+
N3*EDISONSTRASSE 1~
|
214
|
+
N4*BRETTEN**75015*DE~
|
215
|
+
N1*SU*SUPLIER NAME*ZZ*11222333~
|
216
|
+
N3*203 STREET NAME~
|
217
|
+
N4*ATLANTA*GA*30309*US~
|
218
|
+
LIN**BP*MATERIAL1*EC*ENGINEERING1*DR*001~
|
219
|
+
UIT*EA~
|
220
|
+
PER*SC*SEEBURGER INFO*TE*+49(7525)0~
|
221
|
+
FST*13*C*D*20231029****DO*12345-1~
|
222
|
+
FST*77*C*D*20231119****DO*12345-2~
|
223
|
+
FST*68*C*D*20231203****DO*12345-3~
|
224
|
+
SHP*01*927*011*20231014~
|
225
|
+
REF*SI*Q5880~
|
226
|
+
SHP*02*8557*011*20231014**20231203~
|
227
|
+
CTT*1*5~
|
228
|
+
SE*19*0001~
|
229
|
+
GE*1*0001~
|
230
|
+
IEA*1*000000001~
|
231
|
+
```
|
232
|
+
|
233
|
+
Will be returned as:
|
234
|
+
|
235
|
+
```ruby
|
236
|
+
[
|
237
|
+
["ISA", ["00"], [nil], ["00"], [nil], ["01"], ["SENDER"], ["01"], ["RECEIVER"], [231014], [1200], ["U"], ["00401"], ["000000001"], [1], ["P"], []],
|
238
|
+
["GS", ["SS"], ["APP SENDER"], ["APP RECEIVER"], [20231014], [1200], ["0001"], ["X"], ["004010"]],
|
239
|
+
["ST", [862], ["0001"]],
|
240
|
+
["BSS", ["05"], [12345], [20230414], ["DL"], [20231014], [20231203], [], [], [], ["ORDER1"], ["A"]],
|
241
|
+
["N1", ["MI"], ["SEEBURGER AG"], ["ZZ"], ["00000085"]],
|
242
|
+
["N3", ["EDISONSTRASSE 1"]],
|
243
|
+
["N4", ["BRETTEN"], [], [75015], ["DE"]],
|
244
|
+
["N1", ["SU"], ["SUPLIER NAME"], ["ZZ"], [11222333]],
|
245
|
+
["N3", ["203 STREET NAME"]],
|
246
|
+
["N4", ["ATLANTA"], ["GA"], [30309], ["US"]],
|
247
|
+
["LIN", [], ["BP"], ["MATERIAL1"], ["EC"], ["ENGINEERING1"], ["DR"], ["001"]],
|
248
|
+
["UIT", ["EA"]],
|
249
|
+
["PER", ["SC"], ["SEEBURGER INFO"], ["TE"], ["+49(7525)0"]],
|
250
|
+
["FST", [13], ["C"], ["D"], [20231029], [], [], [], ["DO"], ["12345-1"]],
|
251
|
+
["FST", [77], ["C"], ["D"], [20231119], [], [], [], ["DO"], ["12345-2"]],
|
252
|
+
["FST", [68], ["C"], ["D"], [20231203], [], [], [], ["DO"], ["12345-3"]],
|
253
|
+
["SHP", ["01"], [927], ["011"], [20231014]],
|
254
|
+
["REF", ["SI"], ["Q5880"]],
|
255
|
+
["SHP", ["02"], [8557], ["011"], [20231014], [], [20231203]],
|
256
|
+
["CTT", [1], [5]],
|
257
|
+
["SE", [19], ["0001"]],
|
258
|
+
["GE", [1], ["0001"]],
|
259
|
+
["IEA", [1], ["000000001"]]
|
260
|
+
]
|
261
|
+
```
|
262
|
+
|
263
|
+
|
data/lib/edifact_rails/parser.rb
CHANGED
@@ -10,20 +10,26 @@ module EdifactRails
|
|
10
10
|
|
11
11
|
# Treat the input, split the input string into segments, parse those segments
|
12
12
|
def parse(string)
|
13
|
-
#
|
14
|
-
string = string.gsub(
|
13
|
+
# Remove all carraige returns, and leading and trailing whitespace
|
14
|
+
string = string.delete("\r").gsub(/^\s*(.*)\s*$/, '\1')
|
15
15
|
|
16
|
-
|
16
|
+
@edi_format = detect_edi_format(string)
|
17
|
+
|
18
|
+
# Detects special characters in the UNA segment (edifact) or ISA segment (ansix12),
|
19
|
+
# updates special characters if so
|
17
20
|
detect_special_characters(string)
|
18
21
|
|
19
22
|
# Does some funky regex maniulation to handle escaped special characters
|
20
|
-
|
23
|
+
# Ansix12 does not have escape characters, so we can skip
|
24
|
+
string = handle_duplicate_escape_characters(string) unless @edi_format == EdifactRails::Formats::ANSIX12
|
21
25
|
|
22
26
|
# Split the input string into segments
|
23
|
-
segments =
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
+
segments =
|
28
|
+
if @edi_format == EdifactRails::Formats::ANSIX12
|
29
|
+
string.split(@special_characters[:segment_seperator])
|
30
|
+
else
|
31
|
+
string.split(/(?<!#{Regexp.quote(@special_characters[:escape_character])})#{Regexp.quote(@special_characters[:segment_seperator])}/)
|
32
|
+
end
|
27
33
|
|
28
34
|
# Drop the UNA segment, if present (we have already dealt with it in #detect_special_characters)
|
29
35
|
segments.reject! { |s| s[0..2] == "UNA" }
|
@@ -33,62 +39,92 @@ module EdifactRails
|
|
33
39
|
end
|
34
40
|
|
35
41
|
# Given an input string, return the special characters as defined by the UNA segment
|
36
|
-
|
37
|
-
|
42
|
+
def special_characters(string = "")
|
43
|
+
# If no string is passed, return default edifact characters
|
44
|
+
return EdifactRails::DEFAULT_SPECIAL_CHARACTERS if string.empty?
|
45
|
+
|
46
|
+
string = string.delete("\r").gsub(/^\s*(.*)\s*$/, '\1')
|
47
|
+
@edi_format = detect_edi_format(string)
|
38
48
|
detect_special_characters(string)
|
39
49
|
|
40
|
-
|
41
|
-
component_data_element_seperator: @component_data_element_seperator,
|
42
|
-
data_element_seperator: @data_element_seperator,
|
43
|
-
decimal_notation: @decimal_notation,
|
44
|
-
escape_character: @escape_character,
|
45
|
-
segment_seperator: @segment_seperator
|
46
|
-
}
|
50
|
+
@special_characters
|
47
51
|
end
|
48
52
|
|
49
53
|
private
|
50
54
|
|
51
|
-
def
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
@decimal_notation = decimal_notation
|
63
|
-
@escape_character = escape_character
|
64
|
-
@segment_seperator = segment_seperator
|
55
|
+
def detect_edi_format(string)
|
56
|
+
case string[0..2]
|
57
|
+
when "UNA", "UNB"
|
58
|
+
EdifactRails::Formats::EDIFACT
|
59
|
+
when "STX"
|
60
|
+
EdifactRails::Formats::TRADACOMS
|
61
|
+
when "ISA"
|
62
|
+
EdifactRails::Formats::ANSIX12
|
63
|
+
else
|
64
|
+
raise EdifactRails::UnrecognizedFormat
|
65
|
+
end
|
65
66
|
end
|
66
67
|
|
67
68
|
def detect_special_characters(string)
|
68
|
-
#
|
69
|
-
|
69
|
+
# Format must be EDIFACT or ANSI X12 to set custom characters
|
70
|
+
# Tradacoms uses the defaults
|
71
|
+
return unless [EdifactRails::Formats::EDIFACT, EdifactRails::Formats::ANSIX12].include?(@edi_format)
|
72
|
+
|
73
|
+
# If EDIFACT, UNA tags are optional, so return if it's not present
|
74
|
+
return if @edi_format == EdifactRails::Formats::EDIFACT && string[0..2] != "UNA"
|
75
|
+
|
76
|
+
case @edi_format
|
77
|
+
when EdifactRails::Formats::EDIFACT
|
78
|
+
# UNA segments look like this:
|
79
|
+
#
|
80
|
+
# UNA:+.? '
|
81
|
+
#
|
82
|
+
# UNA followed by 6 special characters which are, in order:
|
83
|
+
# 1. Component data element separator
|
84
|
+
# 2. Data element separator
|
85
|
+
# 3. Decimal notation (must be . or ,)
|
86
|
+
# 4. Release character (aka escape character)
|
87
|
+
# 5. Reserved for future use, so always a space for now
|
88
|
+
# 6. Segment terminator
|
89
|
+
set_special_characters(
|
90
|
+
component_data_element_seperator: string[3],
|
91
|
+
data_element_seperator: string[4],
|
92
|
+
decimal_notation: string[5],
|
93
|
+
escape_character: string[6],
|
94
|
+
segment_seperator: string[8]
|
95
|
+
)
|
96
|
+
when EdifactRails::Formats::ANSIX12
|
97
|
+
# ISA segments look like this:
|
98
|
+
# ISA*00* *00* *01*SENDER *01*RECEIVER *231014*1200*U*00401*000000001*1*P*>~
|
99
|
+
# These are designed to always be the same number of characters, so we can use the hardcoded positions
|
100
|
+
# The special characters are the 4th (default *, data_element_seperator),
|
101
|
+
# 105th, 106th, 103rd, and 3rd characters
|
102
|
+
set_special_characters(
|
103
|
+
data_element_seperator: string[3],
|
104
|
+
component_data_element_seperator: string[104],
|
105
|
+
segment_seperator: string[105]
|
106
|
+
)
|
107
|
+
end
|
108
|
+
end
|
70
109
|
|
71
|
-
|
72
|
-
#
|
73
|
-
|
74
|
-
|
75
|
-
#
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
# 5. Reserved for future use, so always a space for now
|
81
|
-
# 6. Segment terminator
|
82
|
-
set_special_characters(string[3], string[4], string[5], string[6], string[8])
|
110
|
+
def set_special_characters(args = {})
|
111
|
+
# arg keys will overwrite the defaults when present
|
112
|
+
@special_characters = EdifactRails::DEFAULT_SPECIAL_CHARACTERS.merge(args)
|
113
|
+
|
114
|
+
# ANSIX12 files have no escape character or decimal notation character§
|
115
|
+
return unless @edi_format == EdifactRails::Formats::ANSIX12
|
116
|
+
|
117
|
+
@special_characters.delete(:escape_character)
|
118
|
+
@special_characters.delete(:decimal_notation)
|
83
119
|
end
|
84
120
|
|
85
|
-
def
|
121
|
+
def handle_duplicate_escape_characters(string)
|
86
122
|
# Prepare regex
|
87
|
-
|
123
|
+
other_specials_regex = Regexp.quote(
|
88
124
|
[
|
89
|
-
@segment_seperator,
|
90
|
-
@data_element_seperator,
|
91
|
-
@component_data_element_seperator
|
125
|
+
@special_characters[:segment_seperator],
|
126
|
+
@special_characters[:data_element_seperator],
|
127
|
+
@special_characters[:component_data_element_seperator]
|
92
128
|
].join
|
93
129
|
)
|
94
130
|
|
@@ -96,7 +132,7 @@ module EdifactRails
|
|
96
132
|
# the special character is therefore unescaped.
|
97
133
|
# Add a space between these even number of escapes, and the special character
|
98
134
|
#
|
99
|
-
# This means the regex logic for
|
135
|
+
# This means the regex logic for splitting on special characters is now consistent, since there will only ever
|
100
136
|
# be either 0 or 1 escape characters before every special character.
|
101
137
|
#
|
102
138
|
# We have to do this because we can't negative lookbehind for 'an even number of escape characters' since
|
@@ -110,20 +146,30 @@ module EdifactRails
|
|
110
146
|
# "LIN+even????+123" => '+' is not escaped, gsub'ed => "even???? +123" => parsed => ['LIN', ['even??'], [123]]
|
111
147
|
# "LIN+odd???+123" => '+' is escaped, not gsub'ed => "odd???+123" => parsed => ['LIN', ['odd?+123']]
|
112
148
|
string.gsub(
|
113
|
-
/(?<!#{Regexp.quote(@escape_character)})((#{Regexp.quote(@escape_character)}{2})+)([#{
|
149
|
+
/(?<!#{Regexp.quote(@special_characters[:escape_character])})((#{Regexp.quote(@special_characters[:escape_character])}{2})+)([#{other_specials_regex}])/,
|
114
150
|
'\1 \3'
|
115
151
|
)
|
116
152
|
end
|
117
153
|
|
118
154
|
# Split the segment into data elements, take the first as the tag, then parse the rest
|
119
155
|
def parse_segment(segment)
|
156
|
+
segment.chomp("")
|
157
|
+
segment.gsub!(/^\s*(.*)\s*/, '\1')
|
158
|
+
|
120
159
|
# If the input is a tradacoms file, the segment tag will be proceeded by '=' instead of '+'
|
121
160
|
# 'QTY=1+A:B' instead of 'QTY+1+A:B'
|
122
161
|
# Fortunately, this is easily handled by simply changing these "="s into "+"s before the split
|
123
|
-
|
162
|
+
if @edi_format == EdifactRails::Formats::TRADACOMS && segment.length >= 4
|
163
|
+
segment[3] = @special_characters[:data_element_seperator]
|
164
|
+
end
|
124
165
|
|
125
166
|
# Segments are made up of data elements
|
126
|
-
data_elements =
|
167
|
+
data_elements =
|
168
|
+
if @edi_format == EdifactRails::Formats::ANSIX12
|
169
|
+
segment.split(@special_characters[:data_element_seperator])
|
170
|
+
else
|
171
|
+
segment.split(/(?<!#{Regexp.quote(@special_characters[:escape_character])})#{Regexp.quote(@special_characters[:data_element_seperator])}/)
|
172
|
+
end
|
127
173
|
|
128
174
|
# The first element is the tag, pop it off
|
129
175
|
parsed_segment = []
|
@@ -137,7 +183,11 @@ module EdifactRails
|
|
137
183
|
def parse_data_element(element)
|
138
184
|
# Split data element into components
|
139
185
|
components =
|
140
|
-
|
186
|
+
if @edi_format == EdifactRails::Formats::ANSIX12
|
187
|
+
element.split(@special_characters[:component_data_element_seperator])
|
188
|
+
else
|
189
|
+
element.split(/(?<!#{Regexp.quote(@special_characters[:escape_character])})#{Regexp.quote(@special_characters[:component_data_element_seperator])}/)
|
190
|
+
end
|
141
191
|
|
142
192
|
components.map { |component| treat_component(component) }
|
143
193
|
end
|
@@ -149,15 +199,19 @@ module EdifactRails
|
|
149
199
|
|
150
200
|
# Prepare regex
|
151
201
|
all_special_characters_string = [
|
152
|
-
@segment_seperator,
|
153
|
-
@data_element_seperator,
|
154
|
-
@component_data_element_seperator,
|
155
|
-
@escape_character
|
202
|
+
@special_characters[:segment_seperator],
|
203
|
+
@special_characters[:data_element_seperator],
|
204
|
+
@special_characters[:component_data_element_seperator],
|
205
|
+
@special_characters[:escape_character]
|
156
206
|
].join
|
157
207
|
|
158
|
-
|
159
|
-
|
160
|
-
|
208
|
+
unless @edi_format == EdifactRails::Formats::ANSIX12
|
209
|
+
# If the component has escaped characters in it, remove the escape character and return the character as is
|
210
|
+
# "?+" -> "+", "??" -> "?"
|
211
|
+
component.gsub!(
|
212
|
+
/#{Regexp.quote(@special_characters[:escape_character])}([#{Regexp.quote(all_special_characters_string)}])/, '\1'
|
213
|
+
)
|
214
|
+
end
|
161
215
|
|
162
216
|
# Convert empty strings to nils
|
163
217
|
component = nil if component.empty?
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module EdifactRails
|
4
|
+
class Serializer
|
5
|
+
# with_service is used to force the service segment (UNA) at the beginning of the message
|
6
|
+
def serialize(segments, with_service:)
|
7
|
+
# Serialize and join the segments
|
8
|
+
output = segments.map { |segment| serialize_segment(segment) }
|
9
|
+
.join(EdifactRails::DEFAULT_SPECIAL_CHARACTERS[:segment_seperator])
|
10
|
+
|
11
|
+
# Add the UNA segment
|
12
|
+
output.insert(0, "UNA:+.? '") unless segments.first.first == "UNA" || !with_service
|
13
|
+
output + EdifactRails::DEFAULT_SPECIAL_CHARACTERS[:segment_seperator]
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
# Serialize the data elements and join them to serialize the segment
|
19
|
+
def serialize_segment(segment)
|
20
|
+
return if segment.empty?
|
21
|
+
|
22
|
+
# Get the tag
|
23
|
+
tag = segment.first
|
24
|
+
data_elements = segment[1..]
|
25
|
+
|
26
|
+
# Serialize the data elements
|
27
|
+
serialized_elements = data_elements.map { |element| serialize_data_element(element) }
|
28
|
+
|
29
|
+
# Join tag and data elements
|
30
|
+
serialized_elements.prepend(tag).join(EdifactRails::DEFAULT_SPECIAL_CHARACTERS[:data_element_seperator])
|
31
|
+
end
|
32
|
+
|
33
|
+
def serialize_data_element(element)
|
34
|
+
element.map { |component| treat_component(component) }
|
35
|
+
.join(EdifactRails::DEFAULT_SPECIAL_CHARACTERS[:component_data_element_seperator])
|
36
|
+
end
|
37
|
+
|
38
|
+
# Strip, remove escape characters, convert to nil where needed, convert to integer where needed
|
39
|
+
def treat_component(component)
|
40
|
+
return component unless component.is_a? String
|
41
|
+
|
42
|
+
# Prepare regex
|
43
|
+
all_special_characters = [
|
44
|
+
EdifactRails::DEFAULT_SPECIAL_CHARACTERS[:segment_seperator],
|
45
|
+
EdifactRails::DEFAULT_SPECIAL_CHARACTERS[:data_element_seperator],
|
46
|
+
EdifactRails::DEFAULT_SPECIAL_CHARACTERS[:component_data_element_seperator],
|
47
|
+
EdifactRails::DEFAULT_SPECIAL_CHARACTERS[:escape_character]
|
48
|
+
].join
|
49
|
+
|
50
|
+
# If the component has escaped characters in it, prepend the escape character "+" -> "?+", "?" -> "??"
|
51
|
+
component.gsub(/([#{Regexp.quote(all_special_characters)}])/) do |match|
|
52
|
+
EdifactRails::DEFAULT_SPECIAL_CHARACTERS[:escape_character] + match
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
data/lib/edifact_rails.rb
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "edifact_rails/parser"
|
4
|
+
require "edifact_rails/serializer"
|
5
|
+
require "edifact_rails/formats"
|
6
|
+
require "edifact_rails/exceptions"
|
4
7
|
|
5
8
|
module EdifactRails
|
6
9
|
DEFAULT_SPECIAL_CHARACTERS = {
|
@@ -17,11 +20,16 @@ module EdifactRails
|
|
17
20
|
end
|
18
21
|
|
19
22
|
def self.parse_file(file_path)
|
20
|
-
parse(File.read(file_path)
|
23
|
+
parse(File.read(file_path))
|
21
24
|
end
|
22
25
|
|
23
|
-
def self.
|
26
|
+
def self.special_characters(string = "")
|
24
27
|
parser = EdifactRails::Parser.new
|
25
|
-
parser.
|
28
|
+
parser.special_characters(string)
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.serialize(array, with_service: true)
|
32
|
+
serializer = EdifactRails::Serializer.new
|
33
|
+
serializer.serialize array, with_service: with_service
|
26
34
|
end
|
27
35
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: edifact_rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Blackwood
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-06-
|
11
|
+
date: 2024-06-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: byebug
|
@@ -124,7 +124,10 @@ files:
|
|
124
124
|
- LICENSE
|
125
125
|
- README.md
|
126
126
|
- lib/edifact_rails.rb
|
127
|
+
- lib/edifact_rails/exceptions.rb
|
128
|
+
- lib/edifact_rails/formats.rb
|
127
129
|
- lib/edifact_rails/parser.rb
|
130
|
+
- lib/edifact_rails/serializer.rb
|
128
131
|
- lib/edifact_rails/version.rb
|
129
132
|
homepage: https://github.com/david-blackwood/edifact_rails
|
130
133
|
licenses:
|