Created
March 4, 2010 21:03
-
-
Save deathbob/322107 to your computer and use it in GitHub Desktop.
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
---- config/initializers/to_plist.rb | |
require 'rails_extensions/plist' | |
ActiveRecord::Base.class_eval do | |
include Plist | |
end | |
---- rails_extensions/plist.rb | |
module Plist | |
def to_plist(options = {}) | |
hash = ActiveRecord::Serialization::Serializer.new(self, options).serializable_record | |
# hash.to_plist | |
PlistXmlSerializer.new(hash, options).serialize | |
end | |
class PlistXmlSerializer | |
attr_reader :options | |
def initialize(record, options = nil) | |
@record = record | |
@options = options ? options.dup : {} | |
end | |
def builder | |
@builder ||= begin | |
options[:indent] ||= 2 | |
builder = options[:builder] ||= Builder::XmlMarkup.new(:indent => options[:indent]) | |
unless options[:skip_instruct] | |
builder.instruct! | |
builder.declare!(:DOCTYPE, :plist, :PUBLIC, "-//Apple//DTD PLIST 1.0//EN", "http://www.apple.com/DTDs/PropertyList-1.0.dtd" ) | |
options[:skip_instruct] = true | |
end | |
builder | |
end | |
end | |
def serialize | |
if options[:do_not_add_version] | |
build_attributes | |
else | |
builder.plist(:version => "1.0" ) do | |
build_attributes | |
end | |
end | |
end | |
def build_attributes | |
builder.dict do | |
@record.each do |k, v| | |
builder.key k.to_s | |
case v | |
# weird v.class doesn't work, but plain old v does | |
when String | |
builder.string v | |
when Time | |
builder.date v.strftime('%Y-%m-%dT%H:%M:%SZ') | |
when Fixnum | |
builder.integer v | |
when BigDecimal | |
builder.real v | |
when FalseClass | |
builder.false | |
when TrueClass | |
builder.true | |
else | |
builder.string v | |
end | |
end | |
end | |
end | |
# xml.comment!("COMMENT") | |
# xml.declare!("DECLARATION") | |
# xml.cdata!("CDATA") | |
# def to_s | |
# serialize | |
# end | |
# def to_plist(options = {:root => 'dict'}) | |
# options[:indent] ||= 2 | |
# xml = options[:builder] ||= Builder::XmlMarkup.new(:indent => options[:indent]) | |
# unless options[:skip_instruct] | |
# xml.instruct! | |
# xml.declare!(%w{DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"} ) | |
# xml.plist(:version => "1.0" ) do | |
# xml.dict do | |
# self.attributes.each do |k, v| | |
# xml.key k.to_s | |
# xml.string v.to_s | |
# end | |
# end | |
# end | |
# end | |
# end | |
# module Enumerable | |
# def to_plist(*a) | |
# to_a.to_plist(*a) | |
# end | |
# end | |
end | |
end | |
class Array | |
def to_plist(options = {}) | |
raise "Not all elements respond to to_plist" unless all? { |e| e.respond_to? :to_plist } | |
require 'builder' unless defined?(Builder) | |
options = options.dup | |
options[:root] ||= all? { |e| e.is_a?(first.class) && first.class.to_s != "Hash" } ? ActiveSupport::Inflector.pluralize(ActiveSupport::Inflector.underscore(first.class.name)) : "records" | |
options[:children] ||= options[:root].singularize | |
options[:indent] ||= 2 | |
options[:builder] ||= Builder::XmlMarkup.new(:indent => options[:indent]) | |
root = options.delete(:root).to_s | |
children = options.delete(:children) | |
if !options.has_key?(:dasherize) || options[:dasherize] | |
root = root.dasherize | |
end | |
unless options.delete(:skip_instruct) | |
options[:builder].instruct! | |
options[:builder].declare!(:DOCTYPE, :plist, :PUBLIC, "-//Apple//DTD PLIST 1.0//EN", "http://www.apple.com/DTDs/PropertyList-1.0.dtd" ) | |
end | |
opts = options.merge({ :root => children }) | |
plist = options[:builder] | |
# yield plist if block_given? | |
plist.plist(:version => "1.0" ) do | |
if options[:hash] | |
plist.tag!('dict') do | |
each do |e| | |
plist.key e.id | |
e.to_plist(opts.merge({ :skip_instruct => true, :do_not_add_version => true })) | |
end | |
end | |
else | |
plist.tag!('array') do | |
each { |e| e.to_plist(opts.merge({ :skip_instruct => true, :do_not_add_version => true })) } | |
end | |
end | |
end | |
plist.target! | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment