Created
November 29, 2014 06:32
-
-
Save SixArm/8620b78f9bf2a8254a95 to your computer and use it in GitHub Desktop.
Ruby example of Exportable module for creating XML
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
## | |
# Exportable methods to help create XML from models. | |
# | |
# Author: Joel Parker Henderson (joel@joelparkerhenderson.com) | |
# License: GPL | |
# | |
module Exportable | |
## | |
# Get this object's export string, such as an XML element string. | |
# | |
# Example: | |
# | |
# class Item < String | |
# include Exportable | |
# end | |
# | |
# a = Item.new("Hello") | |
# a.export | |
# #=> "<item>Hello</item>" | |
# | |
# Example using a given key: | |
# | |
# a.export("foo") | |
# #=> "<foo>Hello</foo>" | |
# | |
# Example using a given key and given value: | |
# | |
# a.export("foo", "goo") | |
# #=> "<foo>goo</foo>" | |
# | |
def export(key = export_key, value = export_value) | |
"<#{key}>#{value}</#{key}>" | |
end | |
## | |
# Get this object's export key, such as a XML tag name string. | |
# | |
# This default implementation returns the class name, adjusted | |
# so the first letter is lowercase as per XML convention. | |
# | |
# Example: | |
# | |
# class Item < String | |
# include Exportable | |
# end | |
# | |
# a = Item.new | |
# a.export_key | |
# #=> "item" | |
# | |
def export_key | |
self.class.name.sub(/^./){$&.downcase} | |
end | |
## | |
# Get this object's export value, such as an XML tag content string. | |
# | |
# Example: | |
# | |
# class Item < String | |
# include Exportable | |
# end | |
# | |
# a = Item.new("Hello") | |
# a.export_value | |
# #=> "Hello" | |
# | |
def export_value | |
to_s | |
end | |
## | |
# Export an object as an XML string. | |
# | |
# This method has cases for four kinds of objects. | |
# | |
# * Exportable. | |
# * Enumerable with items, such as an Array. | |
# * Enumerable with pairs, such as a Hash. | |
# * Anything else. | |
# | |
# Example: | |
# | |
# class Item < String | |
# include Exportable | |
# end | |
# | |
# class Color < String | |
# include Exportable | |
# end | |
# | |
# a = Item.new | |
# | |
# # Object is Exportable | |
# obj = Color.new("Red") | |
# a.export_object(obj) | |
# #=> "<color>Red</color>" | |
# | |
# # Object is Enumerable with items that are Exportable | |
# obj = [Color.new("Red"), Color.new("Green")] | |
# a.export_object(obj) | |
# #=> "<color>Red</color><color>Green</color>" | |
# | |
# # Object is Enumerable with pairs with vaules that are Exportable | |
# obj = {foo: Color.new("Red"), goo: Color.new("Green")} | |
# a.export_object(obj) | |
# #=> "<foo><color>Red</color></foo><goo><color>Green</color></goo>" | |
# | |
# # Object is anything else, e.g. a String | |
# obj = "Anything" | |
# a.export_object(obj) | |
# #=> "Anything" | |
# | |
def export_object(object) | |
case object | |
when Exportable | |
export_object_when_exportable(object) | |
when Enumerable | |
export_object_when_enumerable(object) | |
else | |
export_object_when_default(object) | |
end | |
end | |
def export_object_when_exportable(object) | |
object.export | |
end | |
def export_object_when_enumerable(object) | |
if object.respond_to?(:each_pair) | |
export_object_when_enumerable_with_pairs(object) | |
else | |
export_object_when_enumerable_with_items(object) | |
end | |
end | |
def export_object_when_enumerable_with_items(object) | |
object.map{|x| | |
export_object(x) | |
}.join | |
end | |
def export_object_when_enumerable_with_pairs(object) | |
object.keys.map{|key| | |
export(key, export_object(object[key])) | |
}.join | |
end | |
def export_object_when_default(object) | |
object.to_s | |
end | |
## | |
# Export an instance variable. | |
# | |
# This implementation calls #export_object on the variable. | |
# | |
# Example: | |
# | |
# class Item | |
# include Exportable | |
# attr_accessor :color | |
# end | |
# | |
# a = Item.new | |
# a.color = "Red" | |
# a.export_instance_variable(:@color) | |
# #=> "<color>Red</color>" | |
# | |
# | |
def export_instance_variable(variable) | |
export( | |
variable.to_s.sub(/^@/,''), | |
export_object(instance_variable_get(variable)) | |
) | |
end | |
## | |
# Export all the instance variables. | |
# | |
# class Item | |
# include Exportable | |
# attr_accessor :color | |
# attr_accessor :size | |
# end | |
# | |
# This implementation calls #export_instance_variable on each variable. | |
# | |
# Example: | |
# | |
# a = Item.new | |
# a.color = "Red" | |
# a.size = "Large" | |
# a.export_instance_variables | |
# #=> "<color>Red</color><size>Large</size>" | |
# | |
# | |
def export_instance_variables | |
instance_variables.map{|variable| | |
export_instance_variable(variable) | |
}.join | |
end | |
## | |
# Export the result of sending a message to this object. | |
# | |
# Example: | |
# | |
# class Item < String | |
# include Exportable | |
# end | |
# | |
# a = Item.new("Hello") | |
# a.export_send("length") | |
# #=> "<length>5</length>" | |
# | |
# Example using a key that is different than the message name: | |
# | |
# a.export_send("foo", "length") | |
# #=> "<foo>5</foo>" | |
# | |
def export_send(key, message_name = nil, *args, &block) | |
export(key, __send__(message_name || key, *args, &block)) | |
end | |
## | |
# Export an enumerable. | |
# | |
# This implementation calls #export on each element. | |
# | |
# class Item < String | |
# attr_accessor :colors | |
# end | |
# | |
# class Color < String | |
# include Exportable | |
# end | |
# | |
# a = Item.new | |
# a.colors = [Color.new("Red"), Color.new("Green")] | |
# a.export_enumerable("colors") | |
# #=> "<colors><color>Red</color><color>Green</color></colors>" | |
# | |
def export_enumerable(key, enumerable = nil) | |
export(key, (enumerable || self.__send__(key)).map(&:export).join) | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment