simple_hl7 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'http://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in simple_hl7.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Rome Portlock
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,188 @@
1
+ # SimpleHl7
2
+
3
+ SimpleHL7 is a library that manages HL7 v2.x documents for interfacing with
4
+ health care systems. The goal of SimpleHL7 is to make it easy to create basic
5
+ HL7 messages while also having the power to create more complex ones. SimpleHL7
6
+ is agnostic of message and segment types, it works only with the basic
7
+ structure of HL7 documents.
8
+
9
+ ## Installation
10
+
11
+ Add this line to your application's Gemfile:
12
+
13
+ gem 'simple_hl7'
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install simple_hl7
22
+
23
+ ## Usage
24
+
25
+ SimpleHL7 can be used for either message creation or parsing.
26
+
27
+ ### Message Creation
28
+
29
+ A simple example:
30
+
31
+ ```ruby
32
+ msg = SimpleHL7::Message.new
33
+ msg.msh[9][1] = "ADT"
34
+ msg.msh[9][2] = "A04"
35
+ msg.msh[10] = "12345678"
36
+ msg.msh[11] = "D"
37
+ msg.msh[12] = "2.5"
38
+
39
+ msg.pid[3] = "454545"
40
+ msg.pid[5][1] = "Doe"
41
+ msg.pid[5][2] = "John"
42
+
43
+ msg.pv1[2] = "O"
44
+
45
+ msg.to_hl7
46
+ ```
47
+
48
+ Would generate the following HL7 string.
49
+
50
+ ```
51
+ MSH|^~\&|||||||ADT^A04|12345678|D|2.5
52
+ PID|||454545||Doe^John
53
+ PV1||O
54
+ ```
55
+
56
+ This is the easiest way to use SimpleHL7, however most of the methods used
57
+ above are syntactic sugar for underlying methods that are explained in detail
58
+ later.
59
+
60
+ ### Adding a segment
61
+
62
+ The easiest way to add a segment to a new message is by calling its three
63
+ letter segment name as a method on the message. For example to create a PID
64
+ segment, do the following:
65
+
66
+ ```ruby
67
+ msg = SimpleHL7::Message.new
68
+ msg.pid
69
+ ```
70
+
71
+ Note that since the MSH segment is always required it is created automatically.
72
+ So if to_hl7 was called on the message above, the result would be
73
+
74
+ ```
75
+ MSH|^~\&|
76
+ PID
77
+ ```
78
+
79
+ ### Repeating segments
80
+
81
+ Using the segment name is the easiest way to create a new segment, but if you
82
+ have more than one segment with the same name it won't work. The first name
83
+ method call will create a segment, but subsequent calls will just reference
84
+ that first created segment.
85
+
86
+ To create multiple segments of the same type use the underlying `add_segment`
87
+ method.
88
+
89
+ ```ruby
90
+ obx1 = msg.add_segment('obx')
91
+ obx2 = msg.add_segment('obx')
92
+ ```
93
+
94
+ To later retreive a certain segment use the `segment` method.
95
+
96
+ ```
97
+ obx2 = msg.segment('obx', 2)
98
+ ```
99
+
100
+ ### Adding components, subcomponents, fields etc.
101
+
102
+ To add values to the message just specifiy the index in brackets
103
+
104
+ ```ruby
105
+ msg = SimpleHL7::Message.new
106
+ msg.msh[12] = '2.5'
107
+ ```
108
+
109
+ To specifiy a certain component use more brackets.
110
+
111
+ ```ruby
112
+ msg = SimpleHL7::Message.new
113
+ msg.msh[9][1] = "ADT"
114
+ msg.msh[9][2] = "A04"
115
+ ```
116
+
117
+ It is important to note that under the hood the the bracket syntax actually
118
+ adds the value to the first subcomponent of the first componenet of the first
119
+ repition in the specified field.
120
+
121
+ This means that:
122
+
123
+ ```ruby
124
+ msg.msh[9] = "ADT"
125
+ msg.msh[9][1] = "ADT"
126
+ msg.msh[9][1][1] = "ADT"
127
+ ```
128
+
129
+ are all equivalent.
130
+
131
+ ### Repeating fields
132
+
133
+ Since repeating fields are less common in HL7 they require a little bit of
134
+ extra work to create using SimpleHL7. Use the `r(index)` method to create
135
+ repeats.
136
+
137
+ ```ruby
138
+ msg.pid[13] = '123-4567'
139
+ msg.pid[13].r(2)[1] = '876-5432'
140
+ ```
141
+
142
+ Creates the following PID segment
143
+
144
+ ```
145
+ PID|||||||||||||123-4567~876-5432
146
+ ```
147
+
148
+ ### HL7 Escaping
149
+
150
+ HL7 special characters are automatically escaped properly when generating HL7,
151
+ without doing any extra work.
152
+
153
+ ```ruby
154
+ msg = SimpleHL7::Message.new
155
+ msg.nte[3] = "Testing & escaping notes"
156
+ msg.to_hl7
157
+ ```
158
+
159
+ Outputs:
160
+
161
+ ```
162
+ MSH|^~\&|
163
+ NTE|||Testing \T\ escaping notes
164
+ ```
165
+
166
+ ### Parsing
167
+
168
+ To parse HL7 string use the parse method
169
+
170
+ ```ruby
171
+ hl7_str = "MSH|^~\\&|||||||ADT^A04|12345678|D|2.5\rPID|||454545||Doe^John"
172
+ msg = SimpleHL7::Message.parse(hl7_str)
173
+ ```
174
+
175
+ Once the message is parsed use to_s to pull out values
176
+
177
+ ```ruby
178
+ msg.pid[5][1].to_s
179
+ => "Doe"
180
+ ```
181
+
182
+ ## Contributing
183
+
184
+ 1. Fork it
185
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
186
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
187
+ 4. Push to the branch (`git push origin my-new-feature`)
188
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
data/lib/simple_hl7.rb ADDED
@@ -0,0 +1,15 @@
1
+ require "simple_hl7/version"
2
+
3
+ module SimpleHL7
4
+ # Your code goes here...
5
+ end
6
+
7
+ require "simple_hl7/separator_characters"
8
+ require "simple_hl7/composite"
9
+ require "simple_hl7/subcomponent"
10
+ require "simple_hl7/component"
11
+ require "simple_hl7/component_container"
12
+ require "simple_hl7/field"
13
+ require "simple_hl7/segment"
14
+ require "simple_hl7/msh_segment"
15
+ require "simple_hl7/message"
@@ -0,0 +1,11 @@
1
+ module SimpleHL7
2
+ class Component < Composite
3
+ def self.current_separator_char(separator_chars)
4
+ separator_chars.subcomponent
5
+ end
6
+
7
+ def self.subcomposite_class
8
+ Subcomponent
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ module SimpleHL7
2
+ class ComponentContainer < Composite
3
+ def self.current_separator_char(separator_chars)
4
+ separator_chars.component
5
+ end
6
+
7
+ def self.subcomposite_class
8
+ Component
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,170 @@
1
+ module SimpleHL7
2
+ # Generic building block of a HL7 message. The parts of the message
3
+ # subclass this, and this class does most of the work.
4
+ class Composite
5
+ # Constructor
6
+ #
7
+ # @param value [String] a value that is passed down to the subclass
8
+ # constructor. This allows us to set values on top level components that
9
+ # are passed down to the lowest component. Default nil.
10
+ def initialize(value = nil)
11
+ @subcomposites = {}
12
+ cls = self.class
13
+ unless value.nil?
14
+ @subcomposites[cls.start_index] = cls.subcomposite_class.new(value)
15
+ end
16
+ end
17
+
18
+ # Set the value of the specified subcomposite.
19
+ # The value is actually passed down to the first subcomposite of the
20
+ # specified subcomposite and so on until it reaches a Subcomponent
21
+ # composite.
22
+ #
23
+ # @param index [Integer] the subcomposite index.
24
+ # @param value [String] the value to set.
25
+ def []=(index, value)
26
+ set_subcomposite(index, self.class.subcomposite_class.new(value))
27
+ end
28
+
29
+ # Get a specific subcomposite.
30
+ #
31
+ # @param index [Integer] The index of the subcomposite.
32
+ # @return [Subcomposite] The subcomposite at index or a new subcomposite
33
+ # if none exists. Note that this returns the Subcomposite object and not
34
+ # the string value. This differs from how []= works, but it seems to make
35
+ # the most sense when dealing with HL7 messages.
36
+ def [](index)
37
+ get_subcomposite(index)
38
+ end
39
+
40
+ # Alias for []
41
+ def get_subcomposite(index)
42
+ subcomposite = @subcomposites[index]
43
+ if subcomposite.nil?
44
+ subcomposite = self.class.subcomposite_class.new
45
+ set_subcomposite(index, subcomposite)
46
+ end
47
+ subcomposite
48
+ end
49
+
50
+ # Sets a specific subcomposite
51
+ #
52
+ # @param index [Integer] the indexs of the subcomposite, if there is an
53
+ # existing compsite at the location it is replaced.
54
+ # @param value [Subcomposite] the new subcomposite object for the
55
+ # specified location.
56
+ def set_subcomposite(index, value)
57
+ @subcomposites[index] = value
58
+ end
59
+
60
+ # Calls the specified block once for each index between the start index
61
+ # and the max specified subcomposite index.
62
+ #
63
+ # @yeild [subcomposite] Gives the subcomposite at the current index to the
64
+ # block. If there isn't a subcomposite specified for the index then nil
65
+ # is passed.
66
+ def each
67
+ start = self.class.start_index
68
+ (start..max_index).each { |i| yield @subcomposites[i] } if max_index
69
+ end
70
+
71
+ # Calls the specified block once for each index between the start index
72
+ # and the max specified subcomposite index and returns an array resulting
73
+ # from the return values of each block.
74
+ #
75
+ # @yeild [subcomposite] Gives the subcomposite at the current index to the
76
+ # block. If there isn't a subcomposite specified for the index then nil
77
+ # is passed.
78
+ def map
79
+ start = self.class.start_index
80
+ (start..max_index).map { |i| yield @subcomposites[i] } if max_index
81
+ end
82
+
83
+ # Get a HL7 string representation of this Composite.
84
+ #
85
+ # @separator_chars [SeparatorChars] The separator characters to be used
86
+ # when converting this Composite to a string of HL7.
87
+ def to_hl7(separator_chars)
88
+ sep_char = self.class.current_separator_char(separator_chars)
89
+ map { |subc| subc.to_hl7(separator_chars) if subc }.join(sep_char)
90
+ end
91
+
92
+ # Get the value stored at the first Subcomponent below this Composite
93
+ def to_s
94
+ @subcomposites[self.class.start_index].to_s
95
+ end
96
+
97
+ # Get all the subcomposites as an array. Note that this array has the
98
+ # actual subcomposite object and not clones, so any changes will affect
99
+ # this class as well.
100
+ def to_a
101
+ a = []
102
+ each {|subc| a << subc}
103
+ a
104
+ end
105
+
106
+ # The index where the first subcomposite is located. This is usually either
107
+ # 1 or 0 depending on the specific Composite.
108
+ def self.start_index
109
+ 1
110
+ end
111
+
112
+ # @abstract The character that is used to separate the subcomposites when
113
+ # generating a HL7 string.
114
+ #
115
+ # @param separator_chars [SeparatorChars] The separator characters in use
116
+ # during the HL7 string conversion.
117
+ def self.current_separator_char(separator_chars)
118
+ raise Exception.new("Subclass Responsibility")
119
+ end
120
+
121
+ # @abstract The class that is used for subcomposites.
122
+ def self.subcomposite_class
123
+ raise Exception.new("Subclass Responsibility")
124
+ end
125
+
126
+ # Create a composite from a HL7 string.
127
+ #
128
+ # @param str [String] The string of HL7.
129
+ # @param separator_chars [SeparatorChars] The separator characters used
130
+ # in the HL7 string.
131
+ # @return [Composite] The parsed composite.
132
+ def self.parse(str, separator_chars)
133
+ composite = new
134
+ parse_subcomposite_hash(str, separator_chars).each do |index, subc|
135
+ composite.set_subcomposite(start_index + index, subc)
136
+ end
137
+ composite
138
+ end
139
+
140
+ private
141
+
142
+ def max_index
143
+ @subcomposites.keys.max
144
+ end
145
+
146
+ class << self
147
+ private
148
+
149
+ # Parses the subcomposites of a HL7 string into a hash
150
+ #
151
+ # @param str [String] The HL7 string to parse.
152
+ # @param separator_chars [SeparatorChars] The separator characters used in
153
+ # the HL7 string.
154
+ # @return A hash of composites, one for each subcomposite in the string
155
+ # that actually had a value. Empty subcomposites are left out of the
156
+ # hash.
157
+ def parse_subcomposite_hash(str, separator_chars)
158
+ subc_strs = str.split(current_separator_char(separator_chars))
159
+ subc_h = {}
160
+ subc_strs.each_with_index do |subc_str, index|
161
+ unless subc_str.empty?
162
+ subc_h[index] = subcomposite_class.parse(subc_str, separator_chars)
163
+ end
164
+ end
165
+ subc_h
166
+ end
167
+ end
168
+
169
+ end
170
+ end
@@ -0,0 +1,23 @@
1
+ module SimpleHL7
2
+ class Field < Composite
3
+ def self.current_separator_char(separator_chars)
4
+ separator_chars.repetition
5
+ end
6
+
7
+ def self.subcomposite_class
8
+ ComponentContainer
9
+ end
10
+
11
+ def []=(index, value)
12
+ get_subcomposite(1)[index] = value
13
+ end
14
+
15
+ def [](index)
16
+ get_subcomposite(1)[index]
17
+ end
18
+
19
+ def r(index)
20
+ get_subcomposite(index)
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,74 @@
1
+ module SimpleHL7
2
+ class Message
3
+ def initialize(default_msh = true)
4
+ @segments = []
5
+ @segments << MSHSegment.new if default_msh
6
+ end
7
+
8
+ def method_missing(meth, *args, &block)
9
+ if meth.to_s =~ /^[a-zA-Z][a-zA-Z0-9]{2}$/
10
+ get_named_segment(meth)
11
+ elsif meth.to_s =~ /^[a-zA-Z][a-zA-Z0-9]{2}_all$/
12
+ seg_name = meth[0..3]
13
+ all_segments(seg_name)
14
+ else
15
+ super
16
+ end
17
+ end
18
+
19
+ def to_hl7
20
+ separator_chars = get_named_segment('MSH').separator_chars
21
+ @segments.map {|s| s.to_hl7(separator_chars)}.join("\r")
22
+ end
23
+
24
+ def to_a
25
+ @segments.reduce([]) {|a, s| a << s.to_a}
26
+ end
27
+
28
+ def segment(name, index=1)
29
+ all = all_segments(name)
30
+ seg = nil
31
+ seg = all[index - 1] if all.size >= index
32
+ seg
33
+ end
34
+
35
+ def add_segment(name)
36
+ segment = Segment.new(name)
37
+ @segments << segment
38
+ segment
39
+ end
40
+
41
+ def append_segment(segment)
42
+ @segments << segment
43
+ segment
44
+ end
45
+
46
+ private
47
+
48
+ def all_segments(name)
49
+ @segments.select {|seg| seg.name == name}
50
+ end
51
+
52
+
53
+ def get_named_segment(name)
54
+ name_str = name.to_s.upcase
55
+ segment = @segments.select {|seg| seg.name == name_str}.first
56
+ unless segment
57
+ segment = Segment.new(name_str)
58
+ @segments << segment
59
+ end
60
+ segment
61
+ end
62
+
63
+ def self.parse(str)
64
+ msg = new(false)
65
+ segment_strs = str.split("\r")
66
+ msh = MSHSegment.parse(segment_strs[0])
67
+ msg.append_segment(msh)
68
+ segment_strs[1, segment_strs.length].each do |seg_str|
69
+ msg.append_segment(Segment.parse(seg_str, msh.separator_chars))
70
+ end
71
+ msg
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,38 @@
1
+ module SimpleHL7
2
+ class MSHSegment < Segment
3
+ def initialize
4
+ super('MSH')
5
+ self[1] = '|'
6
+ self[2] = '^~\&'
7
+ end
8
+
9
+ def separator_chars
10
+ enc_chars = @subcomposites[2].to_s
11
+ SeparatorCharacters.new(@subcomposites[1].to_s,
12
+ enc_chars[0],
13
+ enc_chars[1],
14
+ enc_chars[2],
15
+ enc_chars[3])
16
+ end
17
+
18
+ def self.parse(str)
19
+ msh = new
20
+ msh[1] = str[3]
21
+ msh[2] = str[4..7]
22
+
23
+ fields = parse_subcomposite_hash(str[9, str.length], msh.separator_chars)
24
+ fields.each { |index, subc| msh.set_subcomposite(index + 3, subc) }
25
+ msh
26
+ end
27
+
28
+ def to_hl7(separator_chars)
29
+ sep_char = self.class.current_separator_char(separator_chars)
30
+ base_msh = "#{name}#{self[1]}#{self[2]}"
31
+ max_index = @subcomposites.keys.max
32
+ rest_msh = (3..max_index).map { |i|
33
+ @subcomposites[i].to_hl7(separator_chars) if @subcomposites[i]
34
+ }.join(sep_char)
35
+ [base_msh, rest_msh].join(sep_char)
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,23 @@
1
+ module SimpleHL7
2
+ class Segment < Composite
3
+ def self.start_index
4
+ 0
5
+ end
6
+
7
+ def self.subcomposite_class
8
+ Field
9
+ end
10
+
11
+ def self.current_separator_char(separator_chars)
12
+ separator_chars.field
13
+ end
14
+
15
+ def name
16
+ self[0].to_s
17
+ end
18
+
19
+ def to_a
20
+ super.insert(0, name)
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,8 @@
1
+ module SimpleHL7
2
+ class SeparatorCharacters < Struct.new(:field, :component, :repetition,
3
+ :escape, :subcomponent)
4
+ def self.defaults
5
+ SeparatorCharacters.new('|', '^', '~', '\\', '&')
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,27 @@
1
+ module SimpleHL7
2
+ class Subcomponent < Struct.new(:value)
3
+ def to_hl7(separator_chars)
4
+ hl7 = value
5
+ hl7.gsub!(separator_chars.escape, "\\E\\")
6
+ hl7.gsub!(separator_chars.field, "\\F\\")
7
+ hl7.gsub!(separator_chars.repetition, "\\R\\")
8
+ hl7.gsub!(separator_chars.component, "\\S\\")
9
+ hl7.gsub!(separator_chars.subcomponent, "\\T\\")
10
+ hl7
11
+ end
12
+
13
+ def to_s
14
+ value
15
+ end
16
+
17
+ def self.parse(str, separator_chars)
18
+ value = str
19
+ value.gsub!("\\E\\", separator_chars.escape)
20
+ value.gsub!("\\F\\", separator_chars.field)
21
+ value.gsub!("\\R\\", separator_chars.repetition)
22
+ value.gsub!("\\S\\", separator_chars.component)
23
+ value.gsub!("\\T\\", separator_chars.subcomponent)
24
+ Subcomponent.new(value)
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,3 @@
1
+ module SimpleHL7
2
+ VERSION = "0.1.2"
3
+ end
@@ -0,0 +1,20 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/simple_hl7/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Rome Portlock"]
6
+ gem.email = ["rome@alivecor.com"]
7
+ gem.description = %q{Parse and generate hl7 messages for interfacing with health care systems}
8
+ gem.summary = %q{Parse and generate hl7 messages}
9
+ gem.homepage = "https://github.com/alivecor/simple_hl7"
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "simple_hl7"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = SimpleHL7::VERSION
17
+
18
+ gem.add_development_dependency "pry", "~> 0.9"
19
+ gem.add_development_dependency "rspec", "~> 2.14"
20
+ end
@@ -0,0 +1,22 @@
1
+ require "simple_hl7"
2
+
3
+ module SimpleHL7
4
+ describe ComponentContainer do
5
+ describe "#to_hl7" do
6
+ it "generates proper hl7 for a field with subfields" do
7
+ container = ComponentContainer.new
8
+ container[1] = "foo"
9
+ container[2] = "bar"
10
+ container.to_hl7(SeparatorCharacters.defaults).should == "foo^bar"
11
+ end
12
+
13
+ it "generates proper hl7 for a field with components and subfields" do
14
+ container = ComponentContainer.new
15
+ container[1] = "foo"
16
+ container[1][2] = "bar"
17
+ container[2] = "baz"
18
+ container.to_hl7(SeparatorCharacters.defaults).should == "foo&bar^baz"
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,30 @@
1
+ require "simple_hl7"
2
+
3
+ module SimpleHL7
4
+ describe Component do
5
+ describe "#to_hl7" do
6
+ it "generates proper hl7 for a field with subfields" do
7
+ field = Component.new
8
+ field[1] = "foo"
9
+ field[2] = "bar"
10
+ field.to_hl7(SeparatorCharacters.defaults).should == "foo&bar"
11
+ end
12
+ end
13
+
14
+ describe "[]" do
15
+ it "gets the proper value" do
16
+ field = Component.new
17
+ field[1] = "foo"
18
+ field[1].to_s.should == "foo"
19
+ end
20
+ end
21
+
22
+ describe "#parse" do
23
+ it "parse hl7 correctly" do
24
+ component = Component.parse("foo&bar", SeparatorCharacters.defaults)
25
+ component[1].to_s.should == "foo"
26
+ component[2].to_s.should == "bar"
27
+ end
28
+ end
29
+ end
30
+ end
File without changes
@@ -0,0 +1,15 @@
1
+ require "simple_hl7"
2
+
3
+ module SimpleHL7
4
+ describe Field do
5
+ describe "#to_hl7" do
6
+ it "generates proper hl7 for a field with subfields" do
7
+ field = Field.new
8
+ field[1] = "foo"
9
+ field[2] = "baz"
10
+ field.r(2)[1] = "bar"
11
+ field.to_hl7(SeparatorCharacters.defaults).should == 'foo^baz~bar'
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,37 @@
1
+ require "simple_hl7"
2
+
3
+ module SimpleHL7
4
+ describe Message do
5
+ describe "#to_hl7" do
6
+ it "generates an hl7 message" do
7
+ msg = Message.new
8
+ msg.msh[6] = "accountid"
9
+ msg.pid[5] = "User"
10
+ msg.pid[5][2] = "Test"
11
+ msg.to_hl7.should == "MSH|^~\\&||||accountid\rPID|||||User^Test"
12
+ end
13
+ end
14
+
15
+ describe "#add_segment" do
16
+ it "adds segments properly" do
17
+ msg = Message.new
18
+ obx_1 = msg.add_segment('OBX')
19
+ obx_1[1] = "1"
20
+ obx_2 = msg.add_segment('OBX')
21
+ obx_2[1] = "2"
22
+ msg.segment('OBX', 1)[1].to_s.should == "1"
23
+ msg.segment('OBX', 2)[1].to_s.should == "2"
24
+ end
25
+ end
26
+
27
+ describe "#parse" do
28
+ it "properly parses a hl7 string" do
29
+ msg = Message.parse("MSH|^~\\&||||accountid\rPID|||||User^Test~Repeat")
30
+ msg.msh[6].to_s.should == "accountid"
31
+ msg.pid[5].to_s.should == "User"
32
+ msg.pid[5][2].to_s.should == "Test"
33
+ msg.pid[5].r(2)[1].to_s.should == "Repeat"
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,13 @@
1
+ require "simple_hl7"
2
+
3
+ module SimpleHL7
4
+ describe MSHSegment do
5
+ describe "#parse" do
6
+ it "parses a hl7 string correctly" do
7
+ msh = MSHSegment.parse('MSH|^~\\&|||test')
8
+ msh.separator_chars.field.should == '|'
9
+ msh[5].to_s.should == 'test'
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,23 @@
1
+ require "pry"
2
+ require "simple_hl7"
3
+
4
+ module SimpleHL7
5
+ describe Segment do
6
+ describe "#to_hl7" do
7
+ it "generates a message using the specified separator chars" do
8
+ sep_chars = SeparatorCharacters.defaults
9
+ seg = Segment.new('PID')
10
+ seg[5] = 'test'
11
+ seg.to_hl7(sep_chars).should == 'PID|||||test'
12
+ end
13
+ end
14
+
15
+ describe "#parse" do
16
+ it "parses a hl7 string correctly" do
17
+ sep_chars = SeparatorCharacters.defaults
18
+ seg = Segment.parse('PID|||||test', sep_chars)
19
+ seg[5].to_s.should == 'test'
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,32 @@
1
+ require "simple_hl7"
2
+
3
+ module SimpleHL7
4
+ describe Subcomponent do
5
+ describe "#to_hl7" do
6
+ it "returns the value" do
7
+ subf = Subcomponent.new('test')
8
+ subf.to_hl7(SeparatorCharacters.defaults).should == 'test'
9
+ end
10
+
11
+ it "escapes special characters in a string" do
12
+ subc = Subcomponent.new('peas&carrots')
13
+ subc.to_hl7(SeparatorCharacters.defaults).should == 'peas\T\carrots'
14
+ end
15
+
16
+ it "escapes all special characters" do
17
+ subc = Subcomponent.new('\\&^~|')
18
+ default_chars = SeparatorCharacters.defaults
19
+ subc.to_hl7(default_chars).should == "\\E\\\\T\\\\S\\\\R\\\\F\\"
20
+ end
21
+ end
22
+
23
+ describe "#parse" do
24
+ it "should unescape the special characters" do
25
+ str = "\\E\\\\T\\\\S\\\\R\\\\F\\"
26
+ default_chars = SeparatorCharacters.defaults
27
+ parsed = Subcomponent.parse(str, default_chars)
28
+ parsed.to_s.should == '\\&^~|'
29
+ end
30
+ end
31
+ end
32
+ end
metadata ADDED
@@ -0,0 +1,110 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: simple_hl7
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.2
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Rome Portlock
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2014-02-05 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: pry
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '0.9'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '0.9'
30
+ - !ruby/object:Gem::Dependency
31
+ name: rspec
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: '2.14'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: '2.14'
46
+ description: Parse and generate hl7 messages for interfacing with health care systems
47
+ email:
48
+ - rome@alivecor.com
49
+ executables: []
50
+ extensions: []
51
+ extra_rdoc_files: []
52
+ files:
53
+ - .gitignore
54
+ - Gemfile
55
+ - LICENSE
56
+ - README.md
57
+ - Rakefile
58
+ - lib/simple_hl7.rb
59
+ - lib/simple_hl7/component.rb
60
+ - lib/simple_hl7/component_container.rb
61
+ - lib/simple_hl7/composite.rb
62
+ - lib/simple_hl7/field.rb
63
+ - lib/simple_hl7/message.rb
64
+ - lib/simple_hl7/msh_segment.rb
65
+ - lib/simple_hl7/segment.rb
66
+ - lib/simple_hl7/separator_characters.rb
67
+ - lib/simple_hl7/subcomponent.rb
68
+ - lib/simple_hl7/version.rb
69
+ - simple_hl7.gemspec
70
+ - spec/simple_hl7/component_container_spec.rb
71
+ - spec/simple_hl7/component_spec.rb
72
+ - spec/simple_hl7/composite_spec.rb
73
+ - spec/simple_hl7/field_spec.rb
74
+ - spec/simple_hl7/message_spec.rb
75
+ - spec/simple_hl7/msh_segment_spec.rb
76
+ - spec/simple_hl7/segment_spec.rb
77
+ - spec/simple_hl7/subcomponent_spec.rb
78
+ homepage: https://github.com/alivecor/simple_hl7
79
+ licenses: []
80
+ post_install_message:
81
+ rdoc_options: []
82
+ require_paths:
83
+ - lib
84
+ required_ruby_version: !ruby/object:Gem::Requirement
85
+ none: false
86
+ requirements:
87
+ - - ! '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ required_rubygems_version: !ruby/object:Gem::Requirement
91
+ none: false
92
+ requirements:
93
+ - - ! '>='
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ requirements: []
97
+ rubyforge_project:
98
+ rubygems_version: 1.8.24
99
+ signing_key:
100
+ specification_version: 3
101
+ summary: Parse and generate hl7 messages
102
+ test_files:
103
+ - spec/simple_hl7/component_container_spec.rb
104
+ - spec/simple_hl7/component_spec.rb
105
+ - spec/simple_hl7/composite_spec.rb
106
+ - spec/simple_hl7/field_spec.rb
107
+ - spec/simple_hl7/message_spec.rb
108
+ - spec/simple_hl7/msh_segment_spec.rb
109
+ - spec/simple_hl7/segment_spec.rb
110
+ - spec/simple_hl7/subcomponent_spec.rb