Class: HappyMapper::Item

Inherits:
Object
  • Object
show all
Defined in:
lib/happymapper/item.rb

Direct Known Subclasses

Attribute, Element, TextNode

Constant Summary collapse

Types =
[String, Float, Time, Date, DateTime, Integer, Boolean]

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, type, o = {}) ⇒ Item

options:

:deep   =>  Boolean False to only parse element's children, True to include
            grandchildren and all others down the chain (// in xpath)
:namespace => String Element's namespace if it's not the global or inherited
               default
:parser =>  Symbol Class method to use for type coercion.
:raw    =>  Boolean Use raw node value (inc. tags) when parsing.
:single =>  Boolean False if object should be collection, True for single object
:tag    =>  String Element name if it doesn't match the specified name.


16
17
18
19
20
21
22
23
24
# File 'lib/happymapper/item.rb', line 16

def initialize(name, type, o={})
  self.name = name.to_s
  self.type = type
  #self.tag = o.delete(:tag) || name.to_s
  self.tag = o[:tag] || name.to_s
  self.options = { :single => true }.merge(o.merge(:name => self.name))

  @xml_type = self.class.to_s.split('::').last.downcase
end

Instance Attribute Details

#nameObject

Returns the value of attribute name.



3
4
5
# File 'lib/happymapper/item.rb', line 3

def name
  @name
end

#namespaceObject

Returns the value of attribute namespace.



3
4
5
# File 'lib/happymapper/item.rb', line 3

def namespace
  @namespace
end

#optionsObject

Returns the value of attribute options.



3
4
5
# File 'lib/happymapper/item.rb', line 3

def options
  @options
end

#tagObject

Returns the value of attribute tag.



3
4
5
# File 'lib/happymapper/item.rb', line 3

def tag
  @tag
end

#typeObject

Returns the value of attribute type.



3
4
5
# File 'lib/happymapper/item.rb', line 3

def type
  @type
end

Instance Method Details

#attribute?Boolean

Returns:



99
100
101
# File 'lib/happymapper/item.rb', line 99

def attribute?
  @xml_type == 'attribute'
end

#constantObject



26
27
28
# File 'lib/happymapper/item.rb', line 26

def constant
  @constant ||= constantize(type)
end

#element?Boolean

Returns:



95
96
97
# File 'lib/happymapper/item.rb', line 95

def element?
  @xml_type == 'element'
end

#from_xml_node(node, namespace, xpath_options) ⇒ Object

Parameters:

  • node (XMLNode)

    the xml node that is being parsed

  • namespace (String)

    the name of the namespace

  • xpath_options (Hash)

    additional xpath options



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/happymapper/item.rb', line 35

def from_xml_node(node, namespace, xpath_options)
  
  # If the item is defined as a primitive type then cast the value to that type
  # else if the type is XMLContent then store the xml value
  # else the type, specified, needs to handle the parsing.
  
  if primitive?
    find(node, namespace, xpath_options) do |n|
      if n.respond_to?(:content)
        typecast(n.content)
      else
        typecast(n)
      end
    end
  elsif constant == XmlContent
    find(node, namespace, xpath_options) do |n|
      n = n.children if n.respond_to?(:children)
      n.respond_to?(:to_xml) ? n.to_xml : n.to_s
    end
  else
    
    # When not a primitive type or XMLContent then default to using the
    # class method #parse of the type class. If the option 'parser' has been 
    # defined then call that method on the type class instead of #parse
    
    if options[:parser]
      find(node, namespace, xpath_options) do |n|
        if n.respond_to?(:content) && !options[:raw]
          value = n.content
        else
          value = n.to_s
        end

        begin
          constant.send(options[:parser].to_sym, value)
        rescue
          nil
        end
      end
    else
      constant.parse(node, options.merge(:namespaces => xpath_options))
    end
  end
end

#method_nameObject



107
108
109
# File 'lib/happymapper/item.rb', line 107

def method_name
  @method_name ||= name.tr('-', '_')
end

#primitive?Boolean

Returns true if the type defined for the item is defined in the list of primite types Types.

Returns:

  • (Boolean)

    true if the type defined for the item is defined in the list of primite types Types.



91
92
93
# File 'lib/happymapper/item.rb', line 91

def primitive?
  Types.include?(constant)
end

#text_node?Boolean

Returns:



103
104
105
# File 'lib/happymapper/item.rb', line 103

def text_node?
  @xml_type == 'textnode'
end

#typecast(value) ⇒ String, ...

When the type of the item is a primitive type, this will convert value specifed to the particular primitive type. If it fails during this process it will return the original String value.

Parameters:

  • value (String)

    the string value parsed from the XML value that will be converted to the particular primitive type.

Returns:

  • (String, Float, Time, Date, DateTime, Boolean, Integer)

    the converted value to the new type.



122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/happymapper/item.rb', line 122

def typecast(value)
  return value if value.kind_of?(constant) || value.nil?
  begin        
    if    constant == String    then value.to_s
    elsif constant == Float     then value.to_f
    elsif constant == Time      then Time.parse(value.to_s) rescue Time.at(value.to_i)
    elsif constant == Date      then Date.parse(value.to_s)
    elsif constant == DateTime  then DateTime.parse(value.to_s)
    elsif constant == Boolean   then ['true', 't', '1'].include?(value.to_s.downcase)
    elsif constant == Integer
      # ganked from datamapper
      value_to_i = value.to_i
      if value_to_i == 0 && value != '0'
        value_to_s = value.to_s
        begin
          Integer(value_to_s =~ /^(\d+)/ ? $1 : value_to_s)
        rescue ArgumentError
          nil
        end
      else
        value_to_i
      end
    else
      value
    end
  rescue
    value
  end
end

#xpath(namespace = self.namespace) ⇒ Object



80
81
82
83
84
85
86
87
# File 'lib/happymapper/item.rb', line 80

def xpath(namespace = self.namespace)
  xpath  = ''
  xpath += './/' if options[:deep]
  xpath += "#{namespace}:" if namespace
  xpath += tag
  #puts "xpath: #{xpath}"
  xpath
end