mogox/ruby-hl7

View on GitHub
lib/segment_list_storage.rb

Summary

Maintainability
B
4 hrs
Test Coverage
# This module includes methods for storing segments inside segments.
# has_children(child_types) defines three methods dynamically.

module HL7::Message::SegmentListStorage
  attr_reader :child_types

  def add_child_type(child_type)
    if @child_types
      @child_types << child_type.to_sym
    else
      has_children [ child_type.to_sym ]
    end
  end

  private
  # allows a segment to store other segment objects
  # used to handle associated lists like one OBR to many OBX segments
  def has_children(child_types)
    @child_types = child_types

    define_method_child_types
    define_method_children
    define_method_accepts
  end

  def define_method_child_types
    define_method(:child_types) do
      self.class.child_types
    end
  end

  def define_method_accepts
    self.class_eval do
      define_method('accepts?') do |t|
        t = t.to_sym if t.respond_to?(:to_sym)
        !!child_types.index(t)
      end
    end
  end

  def define_method_children
    self.class_eval do
      define_method(:children) do
        unless @my_children
          p = self
          @my_children ||= []
          @my_children.instance_eval do
            @parental = p
            alias :old_append :<<

            def <<( value )
              # do nothing if value is nil
              return unless value

              # make sure it's an array
              value = [value].flatten
              value.map{|item| append(item)}
            end

            def append(value)
              unless (value && value.kind_of?(HL7::Message::Segment))
                raise HL7::Exception.new( "attempting to append non-segment to a segment list" )
              end

              value.segment_parent = @parental
              k = @parental
              while (k && k.segment_parent && !k.segment_parent.kind_of?(HL7::Message))
                k = k.segment_parent
              end
              k.segment_parent << value if k && k.segment_parent
              old_append( value )
            end
          end
        end
        @my_children
      end
    end
  end
end