Class: X12::Base

Inherits:
Object
  • Object
show all
Defined in:
lib/x12/base.rb

Overview

$Id: Base.rb 70 2009-03-26 19:25:39Z ikk $

Base class for Segment, Composite, and Loop. Contains setable segment_separator, field_separator, and composite_separator fields.

Direct Known Subclasses

Composite, Empty, Loop, Segment

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, arr, repeats = nil) ⇒ Base

Creates a new base element with a given name, array of sub-elements, and array of repeats if any.



38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/x12/base.rb', line 38

def initialize(name, arr, repeats = nil)
  @nodes = arr
  @name = name
  @repeats = repeats
  @next_repeat = nil        # Next repeat of the same element, if any

  @parsed_str = nil

  @segment_separator   = '~'
  @field_separator     = '*'
  @composite_separator = ':'

  #puts "Created #{name} #{object_id} #{self.class}  "

end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(meth, *args, &block) ⇒ Object

The main method implementing Ruby-like access methods for nested elements



147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
# File 'lib/x12/base.rb', line 147

def method_missing(meth, *args, &block)
  str = meth.id2name
  str = str[1..str.length] if str =~ /^_\d+$/ # to avoid pure number names like 270, 997, etc.

  #puts "Missing #{str}"

  if str =~ /=$/
    # Assignment

    str.chop!
    #puts str

    case self
    when X12::Segment
      res = find_field(str)
      throw Exception.new("No field '#{str}' in segment '#{self.name}'") if EMPTY == res
      res.content = args[0].to_s
      #puts res.inspect

    else
      throw Exception.new("Illegal assignment to #{meth} of #{self.class}")
    end # case

  else
    # Retrieval

    res = find(str)
    yield res if block_given?
    res
  end # if assignment

end

Instance Attribute Details

#composite_separatorObject

Returns the value of attribute composite_separator.



34
35
36
# File 'lib/x12/base.rb', line 34

def composite_separator
  @composite_separator
end

#field_separatorObject

Returns the value of attribute field_separator.



34
35
36
# File 'lib/x12/base.rb', line 34

def field_separator
  @field_separator
end

#nameObject (readonly)

Returns the value of attribute name.



33
34
35
# File 'lib/x12/base.rb', line 33

def name
  @name
end

#next_repeatObject

Returns the value of attribute next_repeat.



34
35
36
# File 'lib/x12/base.rb', line 34

def next_repeat
  @next_repeat
end

#nodesObject

Returns the value of attribute nodes.



34
35
36
# File 'lib/x12/base.rb', line 34

def nodes
  @nodes
end

#parsed_strObject

Returns the value of attribute parsed_str.



34
35
36
# File 'lib/x12/base.rb', line 34

def parsed_str
  @parsed_str
end

#repeatsObject (readonly)

Returns the value of attribute repeats.



33
34
35
# File 'lib/x12/base.rb', line 33

def repeats
  @repeats
end

#segment_separatorObject

Returns the value of attribute segment_separator.



34
35
36
# File 'lib/x12/base.rb', line 34

def segment_separator
  @segment_separator
end

Instance Method Details

#[](*args) ⇒ Object

The main method implementing Ruby-like access methods for repeating elements



173
174
175
176
# File 'lib/x12/base.rb', line 173

def [](*args)
  #puts "squares #{args.inspect}"

  return self.to_a[args[0]] || EMPTY
end

#do_repeats(s) ⇒ Object

Try to parse the current element one more time if required. Returns the rest of the string or the same string if no more repeats are found or required.



79
80
81
82
83
84
85
86
87
88
89
# File 'lib/x12/base.rb', line 79

def do_repeats(s)
  if self.repeats.end > 1
    possible_repeat = self.dup
    p_s = possible_repeat.parse(s)
    if p_s
      s = p_s
      self.next_repeat = possible_repeat
    end # if parsed

  end # more repeats

  s
end

#dupObject

Make a deep copy of the element



99
100
101
102
103
104
105
106
107
108
109
# File 'lib/x12/base.rb', line 99

def dup
  n = clone
  n.set_empty!
  n.nodes = n.nodes.dup
  n.nodes.each_index{|i|
    n.nodes[i] = n.nodes[i].dup
    n.nodes[i].set_empty!
  }
  #puts "Duped #{self.class} #{self.name} #{self.object_id} #{super.object_id} -> #{n.name} #{n.super.object_id} #{n.object_id} "

  n
end

#find(e) ⇒ Object

Recursively find a sub-element, which also has to be of type Base.



112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# File 'lib/x12/base.rb', line 112

def find(e)
  #puts "Finding [#{e}] in #{self.class} #{name}"

  case self
    when X12::Loop
    # Breadth first

    res = nodes.find{|i| e==i.name }
    return res if res
    # Depth now

    nodes.each{|i| 
      res = i.find(e) if i.kind_of?(X12::Loop)
      return res unless res.nil? or EMPTY==res # otherwise keep looping

    }
    when X12::Segment
    return find_field(e).to_s
  end # case

  return EMPTY
end

#has_content?Boolean

Check if any of the fields has been set yet

Returns:

  • (Boolean)


193
194
195
# File 'lib/x12/base.rb', line 193

def has_content?
  self.nodes.find{|i| i.has_content?}
end

#inspectObject

Formats a printable string containing the base element’s content



53
54
55
# File 'lib/x12/base.rb', line 53

def inspect
  "#{self.class.to_s.sub(/^.*::/, '')} (#{name}) #{repeats} #{super.inspect[1..-2]} =<#{parsed_str}, #{next_repeat.inspect}> ".gsub(/\\*\"/, '"')
end

#repeat {|res| ... } ⇒ Object

Adds a repeat to a segment or loop. Returns a new segment/loop or self if empty.

Yields:

  • (res)


199
200
201
202
203
204
205
206
207
208
# File 'lib/x12/base.rb', line 199

def repeat
  res = if self.has_content? # Do not repeat an empty segment

          last_repeat = self.to_a[-1]
          last_repeat.next_repeat = last_repeat.dup
        else
          self
        end
  yield res if block_given?
  res
end

#set_empty!Object

Empty out the current element



92
93
94
95
96
# File 'lib/x12/base.rb', line 92

def set_empty!
  @next_repeat = nil
  @parsed_str = nil
  self
end

#show(ind = '') ⇒ Object

Prints a tree-like representation of the element



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/x12/base.rb', line 58

def show(ind = '')
  count = 0
  self.to_a.each{|i|
    #puts "#{ind}#{i.name} #{i.object_id} #{i.super.object_id} [#{count}]: #{i.parsed_str} #{i.super.class}"

    puts "#{ind}#{i.name} [#{count}]: #{i.to_s.sub(/^(.{30})(.*?)(.{30})$/, '\1...\3')}"
    # Force parsing a segment

    if i.kind_of?(X12::Segment) && i.nodes[0]
      i.find_field(i.nodes[0].name)
    end
    i.nodes.each{|j|
      case 
      when j.kind_of?(X12::Base)  then j.show(ind+'  ')
      when j.kind_of?(X12::Field) then puts "#{ind+'  '}#{j.name} -> '#{j.to_s}'"
      end
    } 
    count += 1
  }
end

#sizeObject

Returns number of repeats



188
189
190
# File 'lib/x12/base.rb', line 188

def size
  return self.to_a.size
end

#to_aObject

Present self and all repeats as an array with self being #0



131
132
133
134
135
136
137
138
139
# File 'lib/x12/base.rb', line 131

def to_a
  res = [self]
  nr = self.next_repeat
  while nr do
    res << nr
    nr = nr.next_repeat
  end
  res
end

#to_sObject

Returns a parsed string representation of the element



142
143
144
# File 'lib/x12/base.rb', line 142

def to_s
  @parsed_str || ''
end

#with(&block) ⇒ Object

Yields to accompanying block passing self as a parameter.



179
180
181
182
183
184
185
# File 'lib/x12/base.rb', line 179

def with(&block)
  if block_given?
    yield self 
  else
    throw Exception.new("Method 'with' requires a block.")
  end
end