Class: REXMLUtilityNode

Inherits:
Object show all
Defined in:
lib/merb-core/core_ext/hash.rb

Overview

This is a slighly modified version of the XMLUtilityNode from merb.devjavu.com/projects/merb/ticket/95 ([email protected]) It’s mainly just adding vowels, as I ht cd wth n vwls :) This represents the hard part of the work, all I did was change the underlying parser.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, attributes = {}) ⇒ REXMLUtilityNode

Returns a new instance of REXMLUtilityNode.



253
254
255
256
257
258
259
260
261
262
# File 'lib/merb-core/core_ext/hash.rb', line 253

def initialize(name, attributes = {})
  @name         = name.tr("-", "_")
  # leave the type alone if we don't know what it is
  @type         = self.class.available_typecasts.include?(attributes["type"]) ? attributes.delete("type") : attributes["type"]
  
  @nil_element  = attributes.delete("nil") == "true"
  @attributes   = undasherize_keys(attributes)
  @children     = []
  @text         = false
end

Instance Attribute Details

#attributesObject

:nodoc:



234
235
236
# File 'lib/merb-core/core_ext/hash.rb', line 234

def attributes
  @attributes
end

#childrenObject

:nodoc:



234
235
236
# File 'lib/merb-core/core_ext/hash.rb', line 234

def children
  @children
end

#nameObject

:nodoc:



234
235
236
# File 'lib/merb-core/core_ext/hash.rb', line 234

def name
  @name
end

#typeObject

:nodoc:



234
235
236
# File 'lib/merb-core/core_ext/hash.rb', line 234

def type
  @type
end

Instance Method Details

#add_node(node) ⇒ Object



264
265
266
267
# File 'lib/merb-core/core_ext/hash.rb', line 264

def add_node(node)
  @text = true if node.is_a? String
  @children << node
end

#inner_htmlObject

Get the inner_html of the REXML node.



376
377
378
# File 'lib/merb-core/core_ext/hash.rb', line 376

def inner_html
  @children.join
end

#to_hashObject



269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
# File 'lib/merb-core/core_ext/hash.rb', line 269

def to_hash
  if @type == "file"
    f = StringIO.new(::Base64.decode64(@children.first || ""))  
    class << f
      attr_accessor :original_filename, :content_type
    end
    f.original_filename = attributes['name'] || 'untitled'
    f.content_type = attributes['content_type'] || 'application/octet-stream'
    return {name => f}
  end
  
  if @text
    return { name => typecast_value( translate_xml_entities( inner_html ) ) }
  else
    #change repeating groups into an array
    groups = @children.inject({}) { |s,e| (s[e.name] ||= []) << e; s }
    
    out = nil
    if @type == "array"
      out = []
      groups.each do |k, v|
        if v.size == 1
          out << v.first.to_hash.entries.first.last
        else
          out << v.map{|e| e.to_hash[k]}
        end
      end
      out = out.flatten
      
    else # If Hash
      out = {}
      groups.each do |k,v|
        if v.size == 1
          out.merge!(v.first)
        else
          out.merge!( k => v.map{|e| e.to_hash[k]})
        end
      end
      out.merge! attributes unless attributes.empty?
      out = out.empty? ? nil : out
    end

    if @type && out.nil?
      { name => typecast_value(out) }
    else
      { name => out }
    end
  end
end

#to_htmlObject

Converts the node into a readable HTML node.

Returns

String

The HTML node in text form.



384
385
386
387
# File 'lib/merb-core/core_ext/hash.rb', line 384

def to_html
  attributes.merge!(:type => @type ) if @type
  "<#{name}#{attributes.to_xml_attributes}>#{@nil_element ? '' : inner_html}</#{name}>"
end

#to_sObject

Alias

#to_html



391
392
393
# File 'lib/merb-core/core_ext/hash.rb', line 391

def to_s 
  to_html
end

#translate_xml_entities(value) ⇒ Object

Convert basic XML entities into their literal values.

Parameters

value<~gsub>

An XML fragment.

Returns

~gsub

The XML fragment after converting entities.



359
360
361
362
363
364
365
# File 'lib/merb-core/core_ext/hash.rb', line 359

def translate_xml_entities(value)
  value.gsub(/&lt;/,   "<").
        gsub(/&gt;/,   ">").
        gsub(/&quot;/, '"').
        gsub(/&apos;/, "'").
        gsub(/&amp;/,  "&")
end

#typecast_value(value) ⇒ Object

Typecasts a value based upon its type. For instance, if node has #type == “integer”, #=> 12]}

Parameters

value<String>

The value that is being typecast.

:type options

“integer”

converts value to an integer with #to_i

“boolean”

checks whether value, after removing spaces, is the literal “true”

“datetime”

Parses value using Time.parse, and returns a UTC Time

“date”

Parses value using Date.parse

Returns

Integer, true, false, Time, Date, Object

The result of typecasting value.

Note

If self does not have a “type” key, or if it’s not one of the options specified above, the raw value will be returned.



344
345
346
347
348
# File 'lib/merb-core/core_ext/hash.rb', line 344

def typecast_value(value)
  return value unless @type
  proc = self.class.typecasts[@type]
  proc.nil? ? value : proc.call(value)
end

#undasherize_keys(params) ⇒ Object

Take keys of the form foo-bar and convert them to foo_bar



368
369
370
371
372
373
# File 'lib/merb-core/core_ext/hash.rb', line 368

def undasherize_keys(params)
  params.keys.each do |key, value|
    params[key.tr("-", "_")] = params.delete(key)
  end
  params
end