Method: Sequel::Plugins::XmlSerializer::InstanceMethods#from_xml_node

Defined in:
lib/sequel/plugins/xml_serializer.rb

#from_xml_node(parent, opts = OPTS) ⇒ Object

Update the contents of this instance based on the given XML node, which should be a Nokogiri::XML::Node instance. By default, just calls set with a hash created from the content of the node.

Options:

:associations

Indicates that the associations cache should be updated by creating a new associated object using data from the hash. Should be a Symbol for a single association, an array of symbols for multiple associations, or a hash with symbol keys and dependent association option hash values.

:fields

Changes the behavior to call set_fields using the provided fields, instead of calling set.


225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
# File 'lib/sequel/plugins/xml_serializer.rb', line 225

def from_xml_node(parent, opts=OPTS)
  unless parent
    raise Error, "Malformed XML used"
  end
  if !parent.children.empty? && parent.children.all?{|node| node.is_a?(Nokogiri::XML::Text)}
    raise Error, "XML consisting of just text nodes used"
  end

  if assocs = opts[:associations]
    assocs = case assocs
    when Symbol
      {assocs=>OPTS}
    when Array
      assocs_tmp = {}
      assocs.each{|v| assocs_tmp[v] = OPTS}
      assocs_tmp
    when Hash
      assocs
    else
      raise Error, ":associations should be Symbol, Array, or Hash if present"
    end

    assocs_hash = {}
    assocs.each{|k,v| assocs_hash[k.to_s] = v}
    assocs_present = []
  end

  hash = {}
  populate_associations = {}
  name_proc = model.xml_deserialize_name_proc(opts)
  parent.children.each do |node|
    next if node.is_a?(Nokogiri::XML::Text)
    k = name_proc[node.name]
    if assocs_hash && assocs_hash[k]
      assocs_present << [k.to_sym, node]
    else
      hash[k] = node.key?('nil') ? nil : node.children.first.to_s
    end
  end

  if assocs_present
    assocs_present.each do |assoc, node|
      assoc_opts = assocs[assoc]

      unless r = model.association_reflection(assoc)
        raise Error, "Association #{assoc} is not defined for #{model}"
      end

      populate_associations[assoc] = if r.returns_array?
        node.children.reject{|c| c.is_a?(Nokogiri::XML::Text)}.map{|c| r.associated_class.from_xml_node(c, assoc_opts)}
      else
        r.associated_class.from_xml_node(node, assoc_opts)
      end
    end
  end

  if fields = opts[:fields]
    set_fields(hash, fields, opts)
  else
    set(hash)
  end

  populate_associations.each do |assoc, values|
    associations[assoc] = values
  end

  self
end