Module: ComponentDescriptors::DescriptorInitialization::InstanceMethods

Defined in:
lib/component_descriptors.rb

Instance Method Summary (collapse)

Instance Method Details

- (Boolean) attached?

True if an xml or model node has been attached to this Descriptor. Useful for distinguishing between a Descriptor with a nil extracted_value and one which has never been attached.



539
540
541
# File 'lib/component_descriptors.rb', line 539

def attached?
  xml || model 
end

- (Object) copy

Produces an unattached but instantiated copy of this descriptor and its children. (This is different than dup or clone.)



685
686
687
# File 'lib/component_descriptors.rb', line 685

def copy
  self.class.new(section_key, locator, options, &descriptors)
end

- (Object) extract_values_from_model

If a model node has been set for the descriptor, call the descriptor's section_key on it, or if the model is a Hash, look up the section_key, and store the result in the @extracted_value attribute. Returns the newly stored extracted_value or nil.



571
572
573
574
575
# File 'lib/component_descriptors.rb', line 571

def extract_values_from_model
  debug "DescriptorInitialization#extract_values_from_model calling: #{accessor.inspect} on model: #{model.inspect}"
  self.extracted_value = _extract_values_from_model unless extracted_value
  extracted_value
end

- (Object) extract_values_from_xml

If an xml node has been set for the descriptor, use the descriptor's locator on it and store the result in the nil.



562
563
564
565
# File 'lib/component_descriptors.rb', line 562

def extract_values_from_xml
  debug "DescriptorInitialization#extract_values_from_xml xml: #{xml.inspect}"
  self.extracted_value = xml.nil? ? nil : extract_first_node(locator) unless self.extracted_value
end

- (Boolean) field?

True if this is a field leaf node.



661
662
663
# File 'lib/component_descriptors.rb', line 661

def field?
  false 
end

- (Object) field_name



665
666
667
# File 'lib/component_descriptors.rb', line 665

def field_name
  section_key if field?
end

- (Object) find_innermost_element(locator = self.locator, search_node = xml)

Backs through the given section's locator to find the first non-nil Element node. Given a locator such as 'foo/bar/baz' will try 'foo/bar/baz', then 'foo/bar' then 'foo' looking for a non-nil Element to return.

If no match is made, returns the node we've been searching in.

This is useful to pinpoint validation errors as close to their problem source as possible.



587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
# File 'lib/component_descriptors.rb', line 587

def find_innermost_element(locator = self.locator, search_node = xml)
  debug("DescriptorInitialization:find_innermost_element using #{locator} in #{search_node.inspect}")
  until node = extract_first_node(locator, search_node)
    # clip off the left most [*] predicate or /* path
    md = %r{
      \[[^\]]+\]$ |
      /[^/\[]*$
    }x.match(locator)
    break if md.nil? || md.pre_match == '/'
    locator = md.pre_match
  end
  node ||= search_node 
  node = node.element if node.kind_of?(REXML::Attribute)
  node = node.parent if node.kind_of?(REXML::Text)
  return node
end

- (Object) guarded_accessor

Note that the original reference accessor is aliased to :unguarded_accessor when DescriptorInitialization is included.



641
642
643
644
# File 'lib/component_descriptors.rb', line 641

def guarded_accessor
  return unguarded_accessor if unguarded_accessor
  self.accessor = options[:accessor] || section_key
end

- (Object) guarded_locator

Note that the original locator accessor is aliased to :unguarded_locator when DescriptorInitialization is included.



623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
# File 'lib/component_descriptors.rb', line 623

def guarded_locator
  return unguarded_locator if unguarded_locator
  self.locator = case 
    when template_id   
      then %Q{//#{XMLManipulation::CDA_NAMESPACE}:section[./#{XMLManipulation::CDA_NAMESPACE}:templateId[@root = '#{template_id}']]}
    when locate_by == :attribute
      then "@#{section_key.to_s.camelcase(:lower)}"
    when section_key =~ /[^\w]/
      # non word characters--asume an xpath locator is the section_key
      then section_key
    when section_key.to_s =~ /^\w+/
      # all word characters--assume an element reference
      then "#{XMLManipulation::CDA_NAMESPACE}:#{section_key.to_s.camelcase(:lower)}"
  end 
end

- (Object) index_key



553
554
555
556
# File 'lib/component_descriptors.rb', line 553

def index_key
  key = [parent_index_key, section_key].compact.join('_')
  key.blank? ? nil : key.to_sym
end

- (Object) initialize(section_key, locator, options, &descriptors)



492
493
494
495
496
497
498
499
500
# File 'lib/component_descriptors.rb', line 492

def initialize(section_key, locator, options, &descriptors)
  self.section_key = section_key
  self.locator = locator
  self.options = options || {}
  self.logger = self.options[:logger]
  self.mapping_class = self.options[:mapping]
  self.descriptors = descriptors
  _initialize_subsections
end

- (Object) locate_by

If a locator has not been specified, we can assume a locator based on the section_key, but we need to know whether to construct xpath as an element or an attribute. This returns either :element, or :attribute as a guide for how to construct the locator.



617
618
619
# File 'lib/component_descriptors.rb', line 617

def locate_by
  options_by_type(:locate_by) || :element
end

- (Object) model=(value)

Sets and attaches the given model node to the descriptor, extracting a value based on the section_key.



529
530
531
532
533
534
# File 'lib/component_descriptors.rb', line 529

def model=(value)
  @xml, @extracted_value = nil, nil
  @model = value
  attach_model
  @model
end

- (Boolean) model_has_section?

A model may be flat. Or a model may provide an accessor for a a section of a document, rather than just for fields.

Raises an error if no model attached.

Raises:



547
548
549
550
551
# File 'lib/component_descriptors.rb', line 547

def model_has_section?
  raise(DescriptorError, "No model attached.") unless model
  model_has_section = accessor && model.respond_to?(accessor.to_s)
  model_has_section ||= model.kind_of?(Hash) && model.key?[accessor.to_s]
end

- (Object) options_by_type(key)

First checks to see if the options was specified specially for the current validation_type. If so, returns it, if not, returns the base option.



514
515
516
# File 'lib/component_descriptors.rb', line 514

def options_by_type(key)
  validation_type_overrides[key] || options[key]
end

- (Object) pretty_print(pp)



673
674
675
676
677
678
679
680
681
# File 'lib/component_descriptors.rb', line 673

def pretty_print(pp)
  had_attributes, had_descriptors = false, false 
  pp.group(2, "<#{self.class.to_s.demodulize}:#{self.object_id} #{section_key.inspect} => #{locator.inspect} :index_key => #{index_key.inspect}") do
    had_attributes = _pretty_print_attributes(pp)
    had_descriptors = _pretty_print_descriptors(pp)
  end
  pp.breakable if had_attributes || had_descriptors
  pp.text ">"
end

- (Boolean) repeats?

True if this descriptor may occur one or more times.



656
657
658
# File 'lib/component_descriptors.rb', line 656

def repeats?
  false
end

- (Boolean) required?

True if this descriptor describes a section which must be present.



647
648
649
650
651
652
653
# File 'lib/component_descriptors.rb', line 647

def required?
  unless @required
    @required = options_by_type(:required)
    @required = true if @required.nil?
  end
  return @required
end

- (Object) template_id



604
605
606
607
608
609
610
611
# File 'lib/component_descriptors.rb', line 604

def template_id
  unless @template_id_established
    @template_id = options_by_type(:template_id)
    @template_id ||= section_key.to_s if section_key.to_s =~ /(?:\d+\.\d+)+/
    @template_id_established = true
  end
  @template_id
end

- (Object) to_s



669
670
671
# File 'lib/component_descriptors.rb', line 669

def to_s
  "<#{self.class.to_s.demodulize}:#{self.object_id} #{section_key.inspect} => #{locator.inspect}#{' {...} ' if descriptors}>"
end

- (Object) validation_type



502
503
504
# File 'lib/component_descriptors.rb', line 502

def validation_type
  options[:validation_type] || first_ancestors(:validation_type)
end

- (Object) validation_type_overrides

Hash of options specific to the current validation_type. Typically empty.



507
508
509
# File 'lib/component_descriptors.rb', line 507

def validation_type_overrides
  options[validation_type] || {}
end

- (Object) xml=(value)

Sets and attaches the given xml node to the descriptor, extracting a value based on locator.



520
521
522
523
524
525
# File 'lib/component_descriptors.rb', line 520

def xml=(value)
  @model, @extracted_value = nil, nil
  @xml = value.kind_of?(REXML::Document) ? value.root : value
  attach_xml
  @xml
end