Last active
December 10, 2015 21:59
-
-
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
This file contains hidden or 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
# 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 |
seems to be coming for 3.0.20
https://github.com/rails/rails/pull/8853/files
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
Thats some crazy shit, but so far the only solution I found, thanks for sharing!