Fix serializable_hash with xml generation and default :except option

When generating xml with a custom implementation of serializable_hash,
if using the :except option, it was being overriden by the default AR
implementation that attempts to ignore the inheritance column from STI
automatically. So, if you have an implementation like this:

    def serializable_hash(options={})
      super({ except: %w(some_attr) }.merge!(options))
    end

The :except option was correctly being used for :json generation, but
not for :xml, because the options hash already contained the :except
key with the inheritance column, thus overriding the customization.

This commit fixes this problem by removing the :except logic from the
xml serializer, that happened before calling serializable_hash. Since
serializable_hash also does the same check for inheritance column, this
logic was duplicated in both places, thus it's safe to remove it from
xml serializer (see ActiveRecord::Serialization#serializable_hash).

This is an attempt to solve issue #2498, that claims for a
"Single transformation API for both xml and json representations".
This commit is contained in:
Carlos Antonio da Silva 2012-06-22 00:27:00 -03:00
parent 965b779eb2
commit 8b173f3bc5
3 changed files with 30 additions and 5 deletions

View File

@ -177,11 +177,6 @@ module ActiveRecord #:nodoc:
end
class XmlSerializer < ActiveModel::Serializers::Xml::Serializer #:nodoc:
def initialize(*args)
super
options[:except] = Array(options[:except]) | Array(@serializable.class.inheritance_column)
end
class Attribute < ActiveModel::Serializers::Xml::Serializer::Attribute #:nodoc:
def compute_type
klass = @serializable.class

View File

@ -115,6 +115,21 @@ class JsonSerializationTest < ActiveRecord::TestCase
assert_no_match %r{ContactSti}, json
end
def test_serializable_hash_with_default_except_option_and_excluding_inheritance_column_from_sti
@contact = ContactSti.new(@contact.attributes)
assert_equal 'ContactSti', @contact.type
def @contact.serializable_hash(options={})
super({ except: %w(age) }.merge!(options))
end
json = @contact.to_json
assert_match %r{"name":"Konata Izumi"}, json
assert_no_match %r{age}, json
assert_no_match %r{type}, json
assert_no_match %r{ContactSti}, json
end
def test_serializable_hash_should_not_modify_options_in_argument
options = { :only => :name }
@contact.serializable_hash(options)

View File

@ -142,6 +142,21 @@ class DefaultXmlSerializationTest < ActiveRecord::TestCase
assert_no_match %r{<type}, xml
assert_no_match %r{ContactSti}, xml
end
def test_serializable_hash_with_default_except_option_and_excluding_inheritance_column_from_sti
@contact = ContactSti.new(@contact.attributes)
assert_equal 'ContactSti', @contact.type
def @contact.serializable_hash(options={})
super({ except: %w(age) }.merge!(options))
end
xml = @contact.to_xml
assert_match %r{<name>aaron stack</name>}, xml
assert_no_match %r{age}, xml
assert_no_match %r{<type}, xml
assert_no_match %r{ContactSti}, xml
end
end
class DefaultXmlSerializationTimezoneTest < ActiveRecord::TestCase