From dbd1e6914c74f132144faebe0a5f1194a250b9c9 Mon Sep 17 00:00:00 2001 From: John Maxwell Date: Tue, 14 Jul 2009 23:25:46 -0400 Subject: [PATCH] Patch to ActiveModel's (and ActiveRecord, by association) XML serialization: If two parameters are present in Procs supplied to to_xml's :procs option, the model being serialized will be passed as the second argument. Includes supporting test and documentation --- activemodel/lib/active_model/serializers/xml.rb | 6 +++++- .../serializeration/xml_serialization_test.rb | 12 ++++++++++++ .../active_record/serializers/xml_serializer.rb | 15 +++++++++++++++ activerecord/test/cases/xml_serialization_test.rb | 6 ++++++ 4 files changed, 38 insertions(+), 1 deletions(-) diff --git a/activemodel/lib/active_model/serializers/xml.rb b/activemodel/lib/active_model/serializers/xml.rb index 7cdd281..5f04e93 100644 --- a/activemodel/lib/active_model/serializers/xml.rb +++ b/activemodel/lib/active_model/serializers/xml.rb @@ -153,7 +153,11 @@ module ActiveModel def add_procs if procs = options.delete(:procs) [ *procs ].each do |proc| - proc.call(options) + if proc.arity > 1 + proc.call(options, @serializable) + else + proc.call(options) + end end end end diff --git a/activemodel/test/cases/serializeration/xml_serialization_test.rb b/activemodel/test/cases/serializeration/xml_serialization_test.rb index 57792e9..d060477 100644 --- a/activemodel/test/cases/serializeration/xml_serialization_test.rb +++ b/activemodel/test/cases/serializeration/xml_serialization_test.rb @@ -78,4 +78,16 @@ class XmlSerializationTest < ActiveModel::TestCase test "should serialize yaml" do assert_match %r{--- \n:gem: ruby\n}, @contact.to_xml end + + test "should call proc on object" do + proc = Proc.new { |options| options[:builder].tag!('nationality', 'unknown') } + xml = @contact.to_xml(:procs => [ proc ]) + assert_match %r{unknown}, xml + end + + test 'should supply serializable to second proc argument' do + proc = Proc.new { |options, record| options[:builder].tag!('name-reverse', record.name.reverse) } + xml = @contact.to_xml(:procs => [ proc ]) + assert_match %r{kcats noraa}, xml + end end diff --git a/activerecord/lib/active_record/serializers/xml_serializer.rb b/activerecord/lib/active_record/serializers/xml_serializer.rb index 253fa03..4c0c377 100644 --- a/activerecord/lib/active_record/serializers/xml_serializer.rb +++ b/activerecord/lib/active_record/serializers/xml_serializer.rb @@ -122,6 +122,21 @@ module ActiveRecord #:nodoc: # def # # + # Additionally, the record being serialized will be passed to a Proc's second + # parameter. This allows for ad hoc additions to the resultant document that + # incorporate the context of the record being serialized. And by leveraging the + # closure created by a Proc, to_xml can be used to add elements that normally fall + # outside of the scope of the model -- for example, generating and appending URLs + # associated with models. + # + # proc = Proc.new { |options, record| options[:builder].tag!('name-reverse', record.name.reverse) } + # firm.to_xml :procs => [ proc ] + # + # + # # ... normal attributes as shown above ... + # slangis73 + # + # # Alternatively, you can yield the builder object as part of the +to_xml+ call: # # firm.to_xml do |xml| diff --git a/activerecord/test/cases/xml_serialization_test.rb b/activerecord/test/cases/xml_serialization_test.rb index b499976..e1ad5c1 100644 --- a/activerecord/test/cases/xml_serialization_test.rb +++ b/activerecord/test/cases/xml_serialization_test.rb @@ -174,6 +174,12 @@ class DatabaseConnectedXmlSerializationTest < ActiveRecord::TestCase assert_match %r{Danish}, xml end + def test_dual_arity_procs_are_called_on_object + proc = Proc.new { |options, record| options[:builder].tag!('name-reverse', record.name.reverse) } + xml = authors(:david).to_xml(:procs => [ proc ]) + assert_match %r{divaD}, xml + end + def test_top_level_procs_arent_applied_to_associations author_proc = Proc.new { |options| options[:builder].tag!('nationality', 'Danish') } xml = authors(:david).to_xml(:procs => [ author_proc ], :include => :posts, :indent => 2) -- 1.6.3.3