Skip to content

Instantly share code, notes, and snippets.

@courtenay
Last active December 10, 2015 21:59
Show Gist options
  • Save courtenay/4498771 to your computer and use it in GitHub Desktop.
Save courtenay/4498771 to your computer and use it in GitHub Desktop.
MONKEY PATCH: no "xml type=yaml" in your .to_xml dump of activerecord objects
# RAILS 2.3.15
#
# Since <tag type="yaml"> was removed from rails' xml parsing,
# but not from its to_xml method, rails can't talk to an API
# generated by rails, if you have serialized attributes.
# This can be put in config/initializers and you should probably
# upgrade to rails 3 already. Ugh.
# Three parts:
# Part one:
#
# This makes it so that a hash to_xml doesn't have "<hash>" as
# the root element. This might break your app if you rely on
# this output like so:
# { :foo => "Bar" }.to_xml
# => <hash><foo>Bar</foo></hash>
# because this removes the "<hash>" and "</hash>" parts.
Hash::XML_FORMATTING['hash'] = Proc.new { |hash| hash.to_xml(:skip_instruct=>true, :root => "---fuck---").gsub(/\<\/?---fuck---\>\n/, "").html_safe }
# Part two: remove the "type=yaml" from your xml tag and make it
# "type=hash" which probably breaks some spec somewhere
module ActiveRecord
class XmlSerializer
class Attribute
def compute_type
type = if @record.class.serialized_attributes.has_key?(name)
# this is the only line changed from AR
@record.class.serialized_attributes[name].name.downcase.to_sym
else
@record.class.columns_hash[name].try(:type)
end
case type
when :text
:string
when :time
:datetime
else
type
end
end
end
end
end
# part 3, when building xml we want to dump the xml right in there
# instead of escaping it.
module Builder
class XmlBase < BlankSlate
# this is all copied from xmlbase.rb in rails except for one line....
def method_missing(sym, *args, &block)
text = nil
attrs = nil
sym = "#{sym}:#{args.shift}" if args.first.kind_of?(Symbol)
args.each do |arg|
case arg
when Hash
attrs ||= {}
attrs.merge!(arg)
else
text ||= ''
text << arg.to_s
end
end
if block
unless text.nil?
raise ArgumentError, "XmlMarkup cannot mix a text argument with a block"
end
_indent
_start_tag(sym, attrs)
_newline
_nested_structures(block)
_indent
_end_tag(sym)
_newline
elsif text.nil?
_indent
_start_tag(sym, attrs, true)
_newline
else
_indent
_start_tag(sym, attrs)
#
# this line!
#
# if you have a hash that was serialized as xml already, don't escape it here.
#
if args.size > 0 && args[1][:type] == :hash
_text text # don't escape
else
text! text
end
_end_tag(sym)
_newline
end
@target
end
end
end
@grosser
Copy link

grosser commented Jan 21, 2013

seems to be coming for 3.0.20
https://github.com/rails/rails/pull/8853/files

@grosser
Copy link

grosser commented Jan 21, 2013

FYI monkey-patch:

if Rails.version == "3.0.19"
  ActiveModel::Serializers::Xml::Serializer::Attribute.class_eval do
    def compute_type_with_nil
      return if value.nil?
      compute_type_without_nil
    end
    alias_method_chain :compute_type, :nil
  end
else
  raise "remove this #{__FILE__}"
end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment