Skip to content

Instantly share code, notes, and snippets.

@jpshackelford
Created August 29, 2011 16:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jpshackelford/1178773 to your computer and use it in GitHub Desktop.
Save jpshackelford/1178773 to your computer and use it in GitHub Desktop.
Sample Code for ROXML Text Node Factory
require 'rubygems'
require 'roxml'
xml = '
<library>
<name>Fullerton Public</name>
<phoneNumber>000-000-000</phoneNumber>
<media>
<item>
<medium>cassette-tape</medium>
<title>The Story About Ping</title>
<readBy>A. Reader</readBy>
</item>
<item>
<medium>book</medium>
<title>The Story About Ping</title>
<binding>hardcover</binding>
</item>
</media>
</library>
'
class Library
include ROXML
xml_convention do |s|
c = s.camelcase
c[0..0].to_s.downcase + c[1..-1].to_s
end
xml_accessor :name
xml_accessor :phone_number
end
lib = Library.from_xml( xml ) # pass an IO or String containing the XML
puts lib.to_xml
class Book
include ROXML
xml_accessor :title
xml_accessor :author
end
class Library
xml_accessor :books, :in => :books,
:as => [Book]
end
lib = Library.new
lib.name = 'Fullerton Public'
lib.books = []
a_book = Book.new
a_book.title = 'The Story About Ping'
a_book.author = 'Marjorie Flack'
lib.books << a_book
puts lib.to_xml
puts Library.from_xml( lib.to_xml.to_s ).books.first.title
class Medium
include ROXML
class << self
def register(medium_id = nil, a_class = self)
registry.store(medium_id || id_from_class, a_class)
end
def id_from_class
demod = ActiveSupport::Inflector.demodulize(self.name)
underscored = ActiveSupport::Inflector.underscore(demod)
dasherized = ActiveSupport::Inflector.dasherize(underscored)
end
def class_for(medium_id)
registry[medium_id]
end
def registry
unless Medium.instance_variable_defined?(:@registry)
Medium.instance_variable_set(:@registry, { })
end
Medium.instance_variable_get(:@registry)
end
private :registry
alias __original_from_xml from_xml
def from_xml(xml, *args)
if self == Medium
xml_node = ROXML::XML::Node.from(xml)
if xml_node.nil?
raise "Bad xml for action:\n\t#{xml}"
end
medium_id = xml_node.xpath('medium').first.text.strip
medium_class = @registry[medium_id] if defined?(@registry)
unless medium_class.nil?
medium_class.from_xml(xml_node, *args)
else
$stderr.puts "WARN: no medium for #{medium_id}."
__original_from_xml(xml, *args)
end
else
__original_from_xml(xml, *args)
end
end
end # class methods
xml_name 'medium' # even in subclasses
xml_convention do |s|
c = s.camelcase
c[0..0].to_s.downcase + c[1..-1].to_s
end
xml_accessor :title
xml_accessor :author
end
class CassetteTape < Medium
xml_accessor :read_by
end
self.class.send(:remove_const, :Book )
class Book < Medium
xml_accessor :binding
end
class Library
xml_accessor :media,
:from => 'item',
:in => 'media',
:as => [Medium]
end
CassetteTape.register
Book.register
puts Medium.send(:registry).inspect
lib = Library.from_xml(xml)
lib.media.each do |item|
puts "#{item.title} (#{item.class})"
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment