module XML::Mapping::ClassMethods

The instance methods of this module are automatically added as class methods to a class that includes XML::Mapping.

Public Instance Methods

add_accessor(name) click to toggle source

Add getter and setter methods for a new attribute named name (must be a symbol or a string) to this class, taking care not to replace existing getters/setters. This is a convenience method intended to be called from Node class initializers.

# File lib/xml/mapping/base.rb, line 308
def add_accessor(name)
  # existing methods search. Search for symbols and strings
  #  to be compatible with Ruby 1.8 and 1.9.
  methods = self.instance_methods
  if methods[0].kind_of? Symbol
    getter = :"#{name}"
    setter = :"#{name}="
  else
    getter = "#{name}"
    setter = "#{name}="
  end
  unless methods.include?(getter)
    self.module_eval <<-EOS
      attr_reader :#{name}
    EOS
  end
  unless methods.include?(setter)
    self.module_eval <<-EOS
      attr_writer :#{name}
    EOS
  end
end
all_xml_mapping_nodes(options={:mapping=>nil,:create=>true}) click to toggle source

enumeration of all nodes in effect when marshalling/unmarshalling this class, that is, nodes defined for this class as well as for its superclasses. The nodes are returned in the order of their definition, starting with the topmost superclass that has nodes defined. keyword arguments are the same as for xml_mapping_nodes.

# File lib/xml/mapping/base.rb, line 394
def all_xml_mapping_nodes(options={:mapping=>nil,:create=>true})
  # TODO: we could return a dynamic Enumerable here, or cache
  # the array...
  result = []
  if superclass and superclass.respond_to?(:all_xml_mapping_nodes)
    result += superclass.all_xml_mapping_nodes options
  end
  result += xml_mapping_nodes options
end
default_mapping() click to toggle source

return the current default mapping (:_default initially, or the value set with the latest call to #use_mapping)

# File lib/xml/mapping/base.rb, line 300
def default_mapping
  @default_mapping
end
default_root_element_name() click to toggle source

The default root element name for this class. Equals the class name, with all parent module names stripped, and with capital letters converted to lowercase and preceded by a dash; e.g. “Foo::Bar::MySampleClass” becomes “my-sample-class”.

# File lib/xml/mapping/base.rb, line 435
def default_root_element_name
  self.name.split('::')[-1].gsub(/^(.)/){$1.downcase}.gsub(/(.)([A-Z])/){$1+"-"+$2.downcase}
end
load_from_file(filename, options={:mapping=>:_default}) click to toggle source

Create a new instance of this class from the XML contained in the file named filename. Calls #load_from_xml internally.

# File lib/xml/mapping/base.rb, line 333
def load_from_file(filename, options={:mapping=>:_default})
  xml = REXML::Document.new(File.new(filename))
  load_from_xml xml.root, :mapping=>options[:mapping]
end
load_from_xml(xml, options={:mapping=>:_default}) click to toggle source

Create a new instance of this class from the XML contained in xml (a REXML::Element).

Allocates a new object, then calls fill_from_xml(xml) on it.

# File lib/xml/mapping/base.rb, line 343
def load_from_xml(xml, options={:mapping=>:_default})
  raise(MappingError, "undefined mapping: #{options[:mapping].inspect}")            unless xml_mapping_nodes_hash.has_key?(options[:mapping])
  # create the new object. It is recommended that the class
  # have a no-argument initializer, so try new first. If that
  # doesn't work, try allocate, which bypasses the initializer.
  begin
    obj = self.new
    #TODO: this will normally invoke our base XML::Mapping#initialize, which calls
    #  obj.initialize_xml_mapping, which is called below again (with the correct :mapping parameter).
    #  obj.initialize_xml_mapping calls obj_initializing on all nodes.
    #  So obj_initializing may be called on the nodes twice for this initialization.
    #  Maybe document this for node writers?
  rescue ArgumentError # TODO: this may hide real errors.
                       #   how to statically check whether
                       #   self self.new accepts an empty
                       #   argument list?
    obj = self.allocate
  end
  obj.initialize_xml_mapping :mapping=>options[:mapping]
  obj.fill_from_xml xml, :mapping=>options[:mapping]
  obj
end
mapping_output_formatter(formatter=nil) click to toggle source

the formatter to be used for output formatting when writing xml to character streams (Files/IOs). Combined getter/setter. Defaults to simple (compact/no-whitespace) formatting, may be overridden on a per-call base via options

# File lib/xml/mapping/base.rb, line 443
def mapping_output_formatter(formatter=nil)
  # TODO make it per-mapping
  if formatter
    @mapping_output_formatter = formatter
  end
  @mapping_output_formatter ||= REXML::Formatters::Default.new
end
root_element_name(name=nil, options={:mapping=>@default_mapping}) click to toggle source

The “root element name” of this class (combined getter/setter method).

The root element name is the name of the root element of the XML tree returned by <this class>.#save_to_xml (or, more specifically, <this class>.#pre_save). By default, this method returns the default_root_element_name; you may call this method with an argument to set the root element name to something other than the default. The option argument :mapping specifies the mapping the root element is/will be defined in, it defaults to the current default mapping (:_default initially, or the value set with the latest call to #use_mapping)

# File lib/xml/mapping/base.rb, line 418
def root_element_name(name=nil, options={:mapping=>@default_mapping})
  if Hash===name    # ugly...
    options=name; name=nil
  end
  @root_element_names ||= {}
  if name
    Classes_by_rootelt_names.remove_class root_element_name, options[:mapping], self
    @root_element_names[options[:mapping]] = name
    Classes_by_rootelt_names.create_classes_for(name, options[:mapping]) << self
  end
  @root_element_names[options[:mapping]] || default_root_element_name
end
use_mapping(mapping) click to toggle source

Make mapping the mapping to be used by default in future node declarations in this class. The default can be overwritten on a per-node basis by passing a :mapping option parameter to the node factory method

The initial default mapping in a mapping class is :_default

# File lib/xml/mapping/base.rb, line 291
def use_mapping mapping
  @default_mapping = mapping
  xml_mapping_nodes_hash[mapping] ||= []  # create empty mapping node list if
                                          # there wasn't one before so future calls
                                          # to load/save_xml etc. w/ this mapping don't raise
end
xml_mapping_nodes(options={:mapping=>nil,:create=>true}) click to toggle source

array of all nodes defined in this class, in the order of their definition. Option :create specifies whether or not an empty array should be created and returned if there was none before (if not, an exception is raised). :mapping specifies the mapping the returned nodes must have been defined in; nil means return all nodes regardless of their mapping

# File lib/xml/mapping/base.rb, line 374
def xml_mapping_nodes(options={:mapping=>nil,:create=>true})
  unless options[:mapping]
    return xml_mapping_nodes_hash.values.inject([]){|a1,a2|a1+a2}
  end
  options[:create] = true if options[:create].nil?
  if options[:create]
    xml_mapping_nodes_hash[options[:mapping]] ||= []
  else
    xml_mapping_nodes_hash[options[:mapping]] ||
      raise(MappingError, "undefined mapping: #{options[:mapping].inspect}")
  end
end