diff --git a/activemodel/lib/active_model/serialization.rb b/activemodel/lib/active_model/serialization.rb index 4403ef060b..00cd05b7ef 100644 --- a/activemodel/lib/active_model/serialization.rb +++ b/activemodel/lib/active_model/serialization.rb @@ -87,8 +87,8 @@ def serializable_hash(options = nil) Array(options[:methods]).each { |m| hash[m.to_s] = send(m) if respond_to?(m) } serializable_add_includes(options) do |association, records, opts| - hash[association.to_s] = if records.is_a?(Enumerable) - records.map { |a| a.serializable_hash(opts) } + hash[association.to_s] = if records.respond_to?(:to_ary) + records.to_ary.map { |a| a.serializable_hash(opts) } else records.serializable_hash(opts) end diff --git a/activemodel/lib/active_model/serializers/xml.rb b/activemodel/lib/active_model/serializers/xml.rb index 5084298210..b78f1ff3f3 100644 --- a/activemodel/lib/active_model/serializers/xml.rb +++ b/activemodel/lib/active_model/serializers/xml.rb @@ -115,7 +115,9 @@ def add_associations(association, records, opts) merged_options = opts.merge(options.slice(:builder, :indent)) merged_options[:skip_instruct] = true - if records.is_a?(Enumerable) + if records.respond_to?(:to_ary) + records = records.to_ary + tag = ActiveSupport::XmlMini.rename_key(association.to_s, options) type = options[:skip_types] ? { } : {:type => "array"} association_name = association.to_s.singularize diff --git a/activemodel/test/cases/serialization_test.rb b/activemodel/test/cases/serialization_test.rb index 66b18d65e5..d2ba9fd95d 100644 --- a/activemodel/test/cases/serialization_test.rb +++ b/activemodel/test/cases/serialization_test.rb @@ -105,6 +105,24 @@ def test_include_option_with_empty_association assert_equal expected, @user.serializable_hash(:include => :friends) end + class FriendList + def initialize(friends) + @friends = friends + end + + def to_ary + @friends + end + end + + def test_include_option_with_ary + @user.friends = FriendList.new(@user.friends) + expected = {"email"=>"david@example.com", "gender"=>"male", "name"=>"David", + "friends"=>[{"name"=>'Joe', "email"=>'joe@example.com', "gender"=>'male'}, + {"name"=>'Sue', "email"=>'sue@example.com', "gender"=>'female'}]} + assert_equal expected, @user.serializable_hash(:include => :friends) + end + def test_multiple_includes expected = {"email"=>"david@example.com", "gender"=>"male", "name"=>"David", "address"=>{"street"=>"123 Lane", "city"=>"Springfield", "state"=>"CA", "zip"=>11111}, diff --git a/activemodel/test/cases/serializers/xml_serialization_test.rb b/activemodel/test/cases/serializers/xml_serialization_test.rb index 38aecf51ff..5fa227e0e0 100644 --- a/activemodel/test/cases/serializers/xml_serialization_test.rb +++ b/activemodel/test/cases/serializers/xml_serialization_test.rb @@ -188,6 +188,23 @@ def setup assert_match %r{}, xml end + class FriendList + def initialize(friends) + @friends = friends + end + + def to_ary + @friends + end + end + + test "include option with ary" do + @contact.friends = FriendList.new(@contact.friends) + xml = @contact.to_xml :include => :friends, :indent => 0 + assert_match %r{}, xml + assert_match %r{}, xml + end + test "multiple includes" do xml = @contact.to_xml :indent => 0, :skip_instruct => true, :include => [ :address, :friends ] assert xml.include?(@contact.address.to_xml(:indent => 0, :skip_instruct => true))