X12 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +13 -0
- data/COPYING +502 -0
- data/README +309 -0
- data/Rakefile +157 -0
- data/TODO +6 -0
- data/doc/classes/X12.html +174 -0
- data/doc/classes/X12/Base.html +677 -0
- data/doc/classes/X12/Composite.html +156 -0
- data/doc/classes/X12/Empty.html +186 -0
- data/doc/classes/X12/Field.html +339 -0
- data/doc/classes/X12/Loop.html +202 -0
- data/doc/classes/X12/Parser.html +306 -0
- data/doc/classes/X12/Segment.html +277 -0
- data/doc/classes/X12/Table.html +198 -0
- data/doc/created.rid +1 -0
- data/doc/files/CHANGELOG.html +108 -0
- data/doc/files/README.html +474 -0
- data/doc/files/TODO.html +95 -0
- data/doc/files/lib/X12/Base_rb.html +83 -0
- data/doc/files/lib/X12/Composite_rb.html +83 -0
- data/doc/files/lib/X12/Empty_rb.html +83 -0
- data/doc/files/lib/X12/Field_rb.html +83 -0
- data/doc/files/lib/X12/Loop_rb.html +83 -0
- data/doc/files/lib/X12/Parser_rb.html +83 -0
- data/doc/files/lib/X12/Segment_rb.html +83 -0
- data/doc/files/lib/X12/Table_rb.html +83 -0
- data/doc/files/lib/X12_rb.html +100 -0
- data/doc/fr_class_index.html +35 -0
- data/doc/fr_file_index.html +38 -0
- data/doc/fr_method_index.html +62 -0
- data/doc/index.html +27 -0
- data/doc/rdoc-style.css +208 -0
- data/example/factory.rb +92 -0
- data/example/parse.rb +56 -0
- data/lib/X12.rb +50 -0
- data/lib/X12/Base.rb +192 -0
- data/lib/X12/Composite.rb +37 -0
- data/lib/X12/Empty.rb +43 -0
- data/lib/X12/Field.rb +81 -0
- data/lib/X12/Loop.rb +74 -0
- data/lib/X12/Parser.rb +98 -0
- data/lib/X12/Segment.rb +92 -0
- data/lib/X12/Table.rb +44 -0
- data/lib/X12/x12syntax.treetop +256 -0
- data/misc/997.d12 +885 -0
- data/misc/rdoc_template.rb +697 -0
- data/test/tc_factory_997.rb +130 -0
- data/test/tc_parse_997.rb +146 -0
- data/test/ts_x12.rb +27 -0
- metadata +108 -0
data/README
ADDED
@@ -0,0 +1,309 @@
|
|
1
|
+
= X12Parser - a library to manipulate X12 structures using native Ruby syntax
|
2
|
+
|
3
|
+
$Id: README 40 2008-11-13 19:51:31Z ikk $
|
4
|
+
|
5
|
+
*WARNING* <tt>The project is in development. Contributors are welcome.</tt>
|
6
|
+
|
7
|
+
Project home is at http://rubyforge.org/projects/x12parser/. Please
|
8
|
+
note, this is a different project from {Chris Parker's port}[http://rubyforge.org/projects/x12-parser/] of
|
9
|
+
{X12::Parser Perl module}[http://search.cpan.org/~prasad/X12-0.09/lib/X12/Parser.pm].
|
10
|
+
|
11
|
+
== The goal
|
12
|
+
|
13
|
+
The idea is to access X12 messages directly from Ruby, i.e., using a
|
14
|
+
syntax like
|
15
|
+
|
16
|
+
message.L1000.L1010[1].AK4.DataElementReferenceNumber
|
17
|
+
|
18
|
+
This syntax can be used to get and set any field of an X12 message and
|
19
|
+
it makes X12 parsing much more straightforward and self-documenting.
|
20
|
+
|
21
|
+
== The problem
|
22
|
+
|
23
|
+
X12 is a set of "standards" possessing all the elegance of an elephant
|
24
|
+
designed by committee, and quite literally so, see http://www.x12.org.
|
25
|
+
X12 defines rough syntax for specifying text messages, but each of
|
26
|
+
more than 300 specifications defines its own message structure. While
|
27
|
+
messages themselves are easy to parse with a simple tokenizer, their
|
28
|
+
semantics is heavily dependent on the domain. For example, this is
|
29
|
+
X12/997 message conveying "Functional Acknowledgment":
|
30
|
+
|
31
|
+
ST*997*2878~AK1*HS*293328532~AK2*270*307272179~AK3*NM1*8*L1010_0*8~
|
32
|
+
AK4*0:0*66*1~AK4*0:1*66*1~AK4*0:2*66*1~AK3*NM1*8*L1010_1*8~AK4*1:0*
|
33
|
+
66*1~AK4*1:1*66*1~AK3*NM1*8*L1010_2*8~AK4*2:0*66*1~AK5*R*5~AK9*R*1*
|
34
|
+
1*0~SE*8*2878~
|
35
|
+
|
36
|
+
I.e., X12 defines an alphabet and somewhat of a dictionary - not a
|
37
|
+
grammar or semantics for each particular data interchange
|
38
|
+
conversation. Because of many entrenched implementations and
|
39
|
+
government mandates, the X12 is not going to die anytime soon,
|
40
|
+
unfortunately.
|
41
|
+
|
42
|
+
The message above can be easily represented in Ruby as a nested array:
|
43
|
+
|
44
|
+
m = [
|
45
|
+
['ST', '997', '2878'],
|
46
|
+
['AK1', 'HS', '293328532'],
|
47
|
+
['AK2', '270', '307272179'],
|
48
|
+
['AK3', 'NM1', '8', 'L1010_0', '8'],
|
49
|
+
['AK4', '0:0', '66', '1'],
|
50
|
+
['AK4', '0:1', '66', '1'],
|
51
|
+
['AK4', '0:2', '66', '1'],
|
52
|
+
['AK3', 'NM1', '8', 'L1010_1', '8'],
|
53
|
+
['AK4', '1:0', '66', '1'],
|
54
|
+
['AK4', '1:1', '66', '1'],
|
55
|
+
['AK3', 'NM1', '8', 'L1010_2', '8'],
|
56
|
+
['AK4', '2:0', '66', '1'],
|
57
|
+
['AK5', 'R', '5'],
|
58
|
+
['AK9', 'R', '1', '1', '0'],
|
59
|
+
['SE', '8', '2878'],
|
60
|
+
]
|
61
|
+
|
62
|
+
but it will not help any since, say, segment 'AK4' is ambiguously
|
63
|
+
defined and its meaning not at all obvious until the message's
|
64
|
+
structure is interpreted and correct 'AK4' segment is found.
|
65
|
+
|
66
|
+
== The solution
|
67
|
+
|
68
|
+
=== Message structure
|
69
|
+
|
70
|
+
Each participant in EDI has to know the structure of the data coming
|
71
|
+
across the wire - X12 or no X12. The X12 structures are defined in
|
72
|
+
so-called Implementation Guides - thick books with all the data pieces
|
73
|
+
spelled out. There is no other choice, but to invent a
|
74
|
+
computer-readable definition language that will codify these
|
75
|
+
books. For example, the X12/997 message can be defined as
|
76
|
+
|
77
|
+
loop 997 1:1
|
78
|
+
{
|
79
|
+
segment ST 1:1
|
80
|
+
segment AK1 1:1
|
81
|
+
loop L1000 0:999999
|
82
|
+
{
|
83
|
+
segment AK2 0:1
|
84
|
+
loop L1010 0:999999
|
85
|
+
{
|
86
|
+
segment AK3 0:1
|
87
|
+
segment AK4 0:99
|
88
|
+
} # L1010
|
89
|
+
segment AK5 1:1
|
90
|
+
} # L1000
|
91
|
+
segment AK9 1:1
|
92
|
+
segment SE 1:1
|
93
|
+
} # 997
|
94
|
+
|
95
|
+
Namely, the 997 is a 'loop' containing segments ST (only one - '1:1'),
|
96
|
+
AK1 (also only one), another loop L1000 (zero or many repeats),
|
97
|
+
segments AK9 and SE. The loop L1000 can contain a segment AK2
|
98
|
+
(optional - '0:1') and another loop L1010 (zero or many), and so on.
|
99
|
+
|
100
|
+
The segments' structure can be further defined as, for example,
|
101
|
+
|
102
|
+
segment AK2 {
|
103
|
+
TransactionSetIdentifierCode S R 3-3 Tbl143
|
104
|
+
TransactionSetControlNumber S R 4-9
|
105
|
+
} # AK2
|
106
|
+
|
107
|
+
wihch defines a segment AK2 as having to fields:
|
108
|
+
TransactionSetIdentifierCode and TransactionSetControlNumber. The
|
109
|
+
field TransactionSetIdentifierCode is defined as having a type of
|
110
|
+
string ('S'), begin required ('R'), having length of minimum 3 and
|
111
|
+
maximum 3 characters ('3-3'), and being validated against a table
|
112
|
+
Tbl143. The validation table is defined as
|
113
|
+
|
114
|
+
table Tbl143 {
|
115
|
+
100 Insurance Plan Description
|
116
|
+
101 Name and Address Lists
|
117
|
+
...
|
118
|
+
997 Functional Acknowledgment
|
119
|
+
998 Set Cancellation
|
120
|
+
} # Tbl143
|
121
|
+
|
122
|
+
where required values are first tokens on each line, i.e., 100, 101,
|
123
|
+
..., 997, 998.
|
124
|
+
|
125
|
+
This message is fully flashed out in an example 'misc/997.d12' file,
|
126
|
+
copied from the ASC X12N 276/277 (004010X093) "Health Care
|
127
|
+
Claim Status Request and Response" National Electronic Data
|
128
|
+
Interchange Transaction Set Implementation Guide.
|
129
|
+
|
130
|
+
Now expressions like
|
131
|
+
|
132
|
+
message.L1000.L1010[1].AK4.DataElementReferenceNumber
|
133
|
+
|
134
|
+
start making sense of sorts, overall X12's idiocy notwithstanding - it's
|
135
|
+
a field called 'DataElementReferenceNumber' of a first of possibly
|
136
|
+
many segments 'AK4' found in the second repeat of the loop 'L1010'
|
137
|
+
inside the enclosing loop 'L1000'. The meaning of the value '66' found
|
138
|
+
in this field is still in the eye of the beholder, but, at least its
|
139
|
+
location is clearly identified in the message.
|
140
|
+
|
141
|
+
|
142
|
+
=== X12 Structure Definition Language (d12)
|
143
|
+
|
144
|
+
The syntax of the X12 structure definition language should be apparent
|
145
|
+
from the '997.d12' file enclosed with the package. The strict definition
|
146
|
+
is formalized in 'lib/X12/x12syntax.treetop' file.
|
147
|
+
|
148
|
+
=== Parsing
|
149
|
+
|
150
|
+
Here is how to parse an X12/997 message (the source is in
|
151
|
+
example/parse.rb):
|
152
|
+
|
153
|
+
require 'x12'
|
154
|
+
|
155
|
+
# Read message definition and create an actual parser
|
156
|
+
# by compiling .d12 file
|
157
|
+
parser = X12::Parser.new('misc/997.d12')
|
158
|
+
|
159
|
+
# Define a test message to parse
|
160
|
+
m997='ST*997*2878~AK1*HS*293328532~AK2*270*307272179~'\
|
161
|
+
'AK3*NM1*8*L1010_0*8~AK4*0:0*66*1~AK4*0:1*66*1~AK4*0:2*'\
|
162
|
+
'66*1~AK3*NM1*8*L1010_1*8~AK4*1:0*66*1~AK4*1:1*66*1~AK3*'\
|
163
|
+
'NM1*8*L1010_2*8~AK4*2:0*66*1~AK5*R*5~AK9*R*1*1*0~SE*8*2878~'
|
164
|
+
|
165
|
+
# Parse the message
|
166
|
+
r = parser.parse('997', m997)
|
167
|
+
|
168
|
+
# Access components of the message as desired
|
169
|
+
|
170
|
+
# Whole ST segment: -> ST*997*2878~
|
171
|
+
puts r.ST
|
172
|
+
|
173
|
+
# One filed, Group Control Number of AK1 -> 293328532
|
174
|
+
puts r.AK1.GroupControlNumber
|
175
|
+
|
176
|
+
# Individual loop, namely, third L1010 sub-loop of
|
177
|
+
# L1000 loop: -> AK3*NM1*8*L1010_2*8~AK4*2:0*66*1~
|
178
|
+
puts r.L1000.L1010[2]
|
179
|
+
|
180
|
+
# First encounter of Data Element Reference Number of the
|
181
|
+
# first L1010 sub-loop of L1000 loop -> 66
|
182
|
+
puts r.L1000.L1010.AK4.DataElementReferenceNumber
|
183
|
+
|
184
|
+
# Number of L1010 sub-loops in L1000 loop -> 3
|
185
|
+
puts r.L1000.L1010.size
|
186
|
+
|
187
|
+
=== Generating
|
188
|
+
|
189
|
+
Here is how to perform a reverse operation and generate a well-formed
|
190
|
+
997 message (the source is in example/factory.rb):
|
191
|
+
|
192
|
+
require 'x12'
|
193
|
+
|
194
|
+
# Read message definition and create an actual parser
|
195
|
+
# by compiling .d12 file
|
196
|
+
parser = X12::Parser.new('misc/997.d12')
|
197
|
+
|
198
|
+
# Make a new 997 message
|
199
|
+
r = parser.factory('997')
|
200
|
+
|
201
|
+
#
|
202
|
+
# Set various fields as desired
|
203
|
+
#
|
204
|
+
|
205
|
+
# Set fields directly
|
206
|
+
r.ST.TransactionSetIdentifierCode = 997
|
207
|
+
r.ST.TransactionSetControlNumber = '2878'
|
208
|
+
|
209
|
+
# Set fields inside a segment (AK1 in this case)
|
210
|
+
r.AK1 { |ak1|
|
211
|
+
ak1.FunctionalIdentifierCode = 'HS'
|
212
|
+
ak1.GroupControlNumber = 293328532
|
213
|
+
}
|
214
|
+
|
215
|
+
# Set fields deeply inside a segment inside
|
216
|
+
# nested loops (L1000/L1010/AK4 in this case)
|
217
|
+
r.L1000.L1010.AK4.DataElementSyntaxErrorCode = 55
|
218
|
+
r.L1000.AK2.TransactionSetIdentifierCode = 270
|
219
|
+
|
220
|
+
# Set nested loops
|
221
|
+
r.L1000.L1010 {|l|
|
222
|
+
l.AK3 {|s|
|
223
|
+
s.SegmentIdCode = 'NM1'
|
224
|
+
s.LoopIdentifierCode = 'L1000D'
|
225
|
+
}
|
226
|
+
l.AK4 {|s|
|
227
|
+
s.CopyOfBadDataElement = 'Bad element'
|
228
|
+
}
|
229
|
+
}
|
230
|
+
|
231
|
+
# Add loop repeats
|
232
|
+
r.L1000.repeat {|l1000|
|
233
|
+
(0..1).each {|loop_repeat| # Two repeats of the loop L1010
|
234
|
+
l1000.L1010.repeat {|l1010|
|
235
|
+
l1010.AK3 {|s|
|
236
|
+
s.SegmentIdCode = 'DMG'
|
237
|
+
s.SegmentPositionInTransactionSet = 0
|
238
|
+
s.LoopIdentifierCode = 'L1010'
|
239
|
+
s.SegmentSyntaxErrorCode = 22
|
240
|
+
} if loop_repeat == 0 # AK3 only in the first repeat of L1010
|
241
|
+
(0..1).each {|ak4_repeat| # Two repeats of the segment AK4
|
242
|
+
l1010.AK4.repeat {|s|
|
243
|
+
s.PositionInSegment = loop_repeat
|
244
|
+
s.DataElementSyntaxErrorCode = ak4_repeat
|
245
|
+
} # s
|
246
|
+
} # ak4_repeat
|
247
|
+
} # l1010
|
248
|
+
} # loop_repeat
|
249
|
+
|
250
|
+
l1000.AK5{|a|
|
251
|
+
a.TransactionSetAcknowledgmentCode = 666
|
252
|
+
a.TransactionSetSyntaxErrorCode4 = 999
|
253
|
+
} # a
|
254
|
+
} # l1000
|
255
|
+
|
256
|
+
# Print the message as a string -> ST*997*2878~AK1*HS*293328532~
|
257
|
+
# AK2*270*~AK3*NM1**L1000D~AK4***55*Bad element~AK5*~AK3*DMG*0*
|
258
|
+
# L1010*22~AK4*0**0~AK4*0**1~AK4*1**0~AK4*1**1~AK5*666****999~
|
259
|
+
# AK9****~SE**~
|
260
|
+
puts r.render
|
261
|
+
|
262
|
+
== Download
|
263
|
+
|
264
|
+
The latest X12 library version can be downloaded from
|
265
|
+
http://rubyforge.org/frs/?group_id=7297
|
266
|
+
|
267
|
+
== Installation
|
268
|
+
|
269
|
+
You can install X12 library with the following command.
|
270
|
+
|
271
|
+
% gem install X12
|
272
|
+
|
273
|
+
If you install directly from the X12*.gem file, it requires these
|
274
|
+
packages to be installed first:
|
275
|
+
* {Treetop}[http://rubyforge.org/projects/treetop/]
|
276
|
+
* {Polyglot}[http://rubyforge.org/projects/polyglot/]
|
277
|
+
|
278
|
+
== License
|
279
|
+
|
280
|
+
X12 library is released under the Lesser GPL license, see
|
281
|
+
http://www.gnu.org/licenses/lgpl.txt
|
282
|
+
|
283
|
+
== Major deficiencies
|
284
|
+
|
285
|
+
* Validation is not implemented.
|
286
|
+
* Field types and sizes are ignored.
|
287
|
+
* No access methods for composites' fields.
|
288
|
+
|
289
|
+
== Wish list
|
290
|
+
|
291
|
+
* .d12 files should have an 'include' facility, so data definitions can be reused for different messages.
|
292
|
+
|
293
|
+
* It would be nice to codify all popular X12 messages in .d12 format.
|
294
|
+
|
295
|
+
== Support
|
296
|
+
|
297
|
+
Please use the following:
|
298
|
+
|
299
|
+
* forums on Rubyforge for general discussions, http://rubyforge.org/forum/?group_id=7297
|
300
|
+
* trackers to submit bugs or feature requests, http://rubyforge.org/tracker/?group_id=7297
|
301
|
+
* to contact the author, send mail to prelude rubyforge org
|
302
|
+
|
303
|
+
== Acknowledgments
|
304
|
+
|
305
|
+
The authors of the project were inspired by the following works:
|
306
|
+
|
307
|
+
1. The Perl X12 parser by Prasad Poruporuthan, http://search.cpan.org/~prasad/X12-0.09/lib/X12/Parser.pm
|
308
|
+
2. The Ruby port of the above by Chris Parker, http://rubyforge.org/projects/x12-parser/
|
309
|
+
3. Treetop Ruby parser, http://treetop.rubyforge.org
|
data/Rakefile
ADDED
@@ -0,0 +1,157 @@
|
|
1
|
+
#--
|
2
|
+
# This file is part of the X12Parser library that provides tools to
|
3
|
+
# manipulate X12 messages using Ruby native syntax.
|
4
|
+
#
|
5
|
+
# http://x12parser.rubyforge.org
|
6
|
+
#
|
7
|
+
# Copyright (C) 2008 APP Design, Inc.
|
8
|
+
#
|
9
|
+
# This library is free software; you can redistribute it and/or
|
10
|
+
# modify it under the terms of the GNU Lesser General Public
|
11
|
+
# License as published by the Free Software Foundation; either
|
12
|
+
# version 2.1 of the License, or (at your option) any later version.
|
13
|
+
#
|
14
|
+
# This library is distributed in the hope that it will be useful,
|
15
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
16
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
17
|
+
# Lesser General Public License for more details.
|
18
|
+
#
|
19
|
+
# You should have received a copy of the GNU Lesser General Public
|
20
|
+
# License along with this library; if not, write to the Free Software
|
21
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
22
|
+
#
|
23
|
+
# $Id: Rakefile 39 2008-11-13 19:43:55Z ikk $
|
24
|
+
#++
|
25
|
+
require 'rubygems'
|
26
|
+
require 'rake'
|
27
|
+
require 'rake/clean'
|
28
|
+
require 'rake/testtask'
|
29
|
+
require 'rake/rdoctask'
|
30
|
+
require 'rake/packagetask'
|
31
|
+
require 'rake/gempackagetask'
|
32
|
+
require 'rake/contrib/rubyforgepublisher'
|
33
|
+
require 'fileutils'
|
34
|
+
require 'pp'
|
35
|
+
|
36
|
+
require File.join(File.dirname(__FILE__), 'lib', 'X12')
|
37
|
+
|
38
|
+
PKG_NAME = 'X12'
|
39
|
+
PKG_VERSION = X12::VERSION
|
40
|
+
PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
|
41
|
+
PKG_DESTINATION = "../#{PKG_NAME}"
|
42
|
+
|
43
|
+
RAKE = $0
|
44
|
+
RUBY_DIR = File.expand_path(File.dirname(RAKE)+'../..')
|
45
|
+
RUBY = "#{RUBY_DIR}/bin/ruby.exe"
|
46
|
+
|
47
|
+
CLEAN.include(
|
48
|
+
'**/*.log',
|
49
|
+
'doc/**/*',
|
50
|
+
'**/*.tmp',
|
51
|
+
'lib/X12/X12syntax.rb'
|
52
|
+
)
|
53
|
+
CLEAN.exclude(
|
54
|
+
)
|
55
|
+
|
56
|
+
|
57
|
+
#puts "Files to clobber: #{CLOBBER}"
|
58
|
+
#puts "Files to clean: #{CLEAN}"
|
59
|
+
|
60
|
+
desc "Default Task"
|
61
|
+
task :default => [ :example, :test ]
|
62
|
+
|
63
|
+
# Run examples
|
64
|
+
task :example do |x|
|
65
|
+
Dir['example/*.rb'].each {|f|
|
66
|
+
puts "Running #{f}"
|
67
|
+
sh(RUBY, '-I', 'lib', f) do |ok, res|
|
68
|
+
fail "Command failed (status = #{res.exitstatus})" unless ok
|
69
|
+
end
|
70
|
+
}
|
71
|
+
end
|
72
|
+
|
73
|
+
task :test do |x|
|
74
|
+
Rake::TestTask.new { |t|
|
75
|
+
t.libs << "test"
|
76
|
+
t.test_files = Dir['test/ts_*.rb']
|
77
|
+
t.verbose = true
|
78
|
+
}
|
79
|
+
end # :test
|
80
|
+
|
81
|
+
file 'doc/index.html' => ['misc/rdoc_template.rb' ]
|
82
|
+
task :rdoc => ['doc/index.html']
|
83
|
+
|
84
|
+
# Generate the RDoc documentation
|
85
|
+
Rake::RDocTask.new { |rdoc|
|
86
|
+
rdoc.rdoc_dir = 'doc'
|
87
|
+
rdoc.title = "X12 -- an X12 parsing library"
|
88
|
+
rdoc.options << '--line-numbers' << '--inline-source' << '--main' << 'README'
|
89
|
+
rdoc.template = 'misc/rdoc_template.rb'
|
90
|
+
rdoc.rdoc_files.include('README')
|
91
|
+
rdoc.rdoc_files.include('CHANGELOG')
|
92
|
+
rdoc.rdoc_files.include('TODO')
|
93
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
94
|
+
}
|
95
|
+
|
96
|
+
|
97
|
+
# Create compressed packages by running 'rake gem'
|
98
|
+
|
99
|
+
desc "gem task"
|
100
|
+
task :gem => [ :clobber, :rdoc ]
|
101
|
+
|
102
|
+
# Here's how to look inside the gem package:
|
103
|
+
# ~..>tar xvf package.gem; gunzip data.tar.gz metadata.gz; tar xvf data.tar; cat metadata
|
104
|
+
spec = Gem::Specification.new do |s|
|
105
|
+
s.platform = Gem::Platform::RUBY
|
106
|
+
s.name = PKG_NAME
|
107
|
+
s.version = PKG_VERSION
|
108
|
+
s.summary = 'X12 parsing and generation library'
|
109
|
+
s.description = 'Library to parse X12 messages and manipulate their loops, segments, fields, composites, and validation tables.'
|
110
|
+
s.author = 'APP Design, Inc.'
|
111
|
+
s.email = 'info@appdesign.com'
|
112
|
+
s.rubyforge_project = PKG_NAME
|
113
|
+
s.homepage = "http://www.appdesign.com"
|
114
|
+
|
115
|
+
s.has_rdoc = true
|
116
|
+
s.requirements << 'none'
|
117
|
+
s.require_path = 'lib'
|
118
|
+
s.autorequire = 'x12'
|
119
|
+
s.add_dependency "treetop"
|
120
|
+
|
121
|
+
[
|
122
|
+
"Rakefile",
|
123
|
+
"README",
|
124
|
+
"TODO",
|
125
|
+
"CHANGELOG",
|
126
|
+
"COPYING",
|
127
|
+
"doc/**/*",
|
128
|
+
"lib/**/*",
|
129
|
+
"test/**/*",
|
130
|
+
"example/**/*",
|
131
|
+
"misc/**/*"
|
132
|
+
].each do |i|
|
133
|
+
s.files += Dir.glob(i).delete_if do
|
134
|
+
|x| x =~ /.*~/
|
135
|
+
end
|
136
|
+
end
|
137
|
+
puts "Files included into the GEM:" if $VERBOSE
|
138
|
+
pp s.files if $VERBOSE
|
139
|
+
|
140
|
+
s.test_files = Dir.glob( "test/**/ts_*rb" )
|
141
|
+
end
|
142
|
+
|
143
|
+
Rake::GemPackageTask.new(spec) do |p|
|
144
|
+
p.gem_spec = spec
|
145
|
+
p.need_tar = true
|
146
|
+
p.need_zip = true
|
147
|
+
end
|
148
|
+
|
149
|
+
# Compile treetop definition into Ruby code. Like this:
|
150
|
+
# >rake lib/X12/X12syntax.rb
|
151
|
+
# It's needed only for debugging Treetop's internals.
|
152
|
+
rule '.rb' => ['.treetop'] do |t|
|
153
|
+
require 'treetop'
|
154
|
+
compiler = Treetop::Compiler::GrammarCompiler.new
|
155
|
+
puts "Compiling [#{t.source}]"
|
156
|
+
compiler.compile(t.source)
|
157
|
+
end
|