From 5b2eb64ceb08cd005dc06b721935de5853971473 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jos=C3=A9=20Valim?= <jose.valim@gmail.com>
Date: Wed, 30 Nov 2011 18:38:28 +0100
Subject: Revert "Implement ArraySerializer and move old serialization API to a
 new namespace."

This reverts commit 8896b4fdc8a543157cdf4dfc378607ebf6c10ab0.

Conflicts:

	activemodel/lib/active_model.rb
	activemodel/lib/active_model/serializable.rb
	activemodel/lib/active_model/serializer.rb
	activemodel/test/cases/serializer_test.rb
---
 activemodel/lib/active_model.rb                   |   1 -
 activemodel/lib/active_model/serializable.rb      | 144 ------------
 activemodel/lib/active_model/serializable/json.rb | 108 ---------
 activemodel/lib/active_model/serializable/xml.rb  | 195 -----------------
 activemodel/lib/active_model/serialization.rb     | 139 +++++++++++-
 activemodel/lib/active_model/serializer.rb        | 253 ----------------------
 activemodel/lib/active_model/serializers/json.rb  | 102 ++++++++-
 activemodel/lib/active_model/serializers/xml.rb   | 191 +++++++++++++++-
 8 files changed, 419 insertions(+), 714 deletions(-)
 delete mode 100644 activemodel/lib/active_model/serializable.rb
 delete mode 100644 activemodel/lib/active_model/serializable/json.rb
 delete mode 100644 activemodel/lib/active_model/serializable/xml.rb
 delete mode 100644 activemodel/lib/active_model/serializer.rb

(limited to 'activemodel/lib')

diff --git a/activemodel/lib/active_model.rb b/activemodel/lib/active_model.rb
index 7ea04344f0..d0e2a6f39c 100644
--- a/activemodel/lib/active_model.rb
+++ b/activemodel/lib/active_model.rb
@@ -43,7 +43,6 @@ module ActiveModel
   autoload :Observer, 'active_model/observing'
   autoload :Observing
   autoload :SecurePassword
-  autoload :Serializable
   autoload :Serialization
   autoload :TestCase
   autoload :Translation
diff --git a/activemodel/lib/active_model/serializable.rb b/activemodel/lib/active_model/serializable.rb
deleted file mode 100644
index 86770a25e4..0000000000
--- a/activemodel/lib/active_model/serializable.rb
+++ /dev/null
@@ -1,144 +0,0 @@
-require 'active_support/core_ext/hash/except'
-require 'active_support/core_ext/hash/slice'
-require 'active_support/core_ext/array/wrap'
-require 'active_support/core_ext/string/inflections'
-
-module ActiveModel
-  # == Active Model Serializable
-  #
-  # Provides a basic serialization to a serializable_hash for your object.
-  #
-  # A minimal implementation could be:
-  #
-  #   class Person
-  #
-  #     include ActiveModel::Serializable
-  #
-  #     attr_accessor :name
-  #
-  #     def attributes
-  #       {'name' => name}
-  #     end
-  #
-  #   end
-  #
-  # Which would provide you with:
-  #
-  #   person = Person.new
-  #   person.serializable_hash   # => {"name"=>nil}
-  #   person.name = "Bob"
-  #   person.serializable_hash   # => {"name"=>"Bob"}
-  #
-  # You need to declare some sort of attributes hash which contains the attributes
-  # you want to serialize and their current value.
-  #
-  # Most of the time though, you will want to include the JSON or XML
-  # serializations. Both of these modules automatically include the
-  # ActiveModel::Serialization module, so there is no need to explicitly
-  # include it.
-  #
-  # So a minimal implementation including XML and JSON would be:
-  #
-  #   class Person
-  #
-  #     include ActiveModel::Serializable::JSON
-  #     include ActiveModel::Serializable::XML
-  #
-  #     attr_accessor :name
-  #
-  #     def attributes
-  #       {'name' => name}
-  #     end
-  #
-  #   end
-  #
-  # Which would provide you with:
-  #
-  #   person = Person.new
-  #   person.serializable_hash   # => {"name"=>nil}
-  #   person.as_json             # => {"name"=>nil}
-  #   person.to_json             # => "{\"name\":null}"
-  #   person.to_xml              # => "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<serial-person...
-  #
-  #   person.name = "Bob"
-  #   person.serializable_hash   # => {"name"=>"Bob"}
-  #   person.as_json             # => {"name"=>"Bob"}
-  #   person.to_json             # => "{\"name\":\"Bob\"}"
-  #   person.to_xml              # => "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<serial-person...
-  #
-  # Valid options are <tt>:only</tt>, <tt>:except</tt> and <tt>:methods</tt> .
-  module Serializable
-    extend ActiveSupport::Concern
-
-    autoload :JSON, "active_model/serializable/json"
-    autoload :XML,  "active_model/serializable/xml"
-
-    def serializable_hash(options = nil)
-      options ||= {}
-
-      attribute_names = attributes.keys.sort
-      if only = options[:only]
-        attribute_names &= Array.wrap(only).map(&:to_s)
-      elsif except = options[:except]
-        attribute_names -= Array.wrap(except).map(&:to_s)
-      end
-
-      hash = {}
-      attribute_names.each { |n| hash[n] = read_attribute_for_serialization(n) }
-
-      method_names = Array.wrap(options[:methods]).select { |n| respond_to?(n) }
-      method_names.each { |n| hash[n] = send(n) }
-
-      serializable_add_includes(options) do |association, records, opts|
-        hash[association] = if records.is_a?(Enumerable)
-          records.map { |a| a.serializable_hash(opts) }
-        else
-          records.serializable_hash(opts)
-        end
-      end
-
-      hash
-    end
-
-  private
-
-    # Hook method defining how an attribute value should be retrieved for
-    # serialization. By default this is assumed to be an instance named after
-    # the attribute. Override this method in subclasses should you need to
-    # retrieve the value for a given attribute differently:
-    #
-    #   class MyClass
-    #     include ActiveModel::Validations
-    #
-    #     def initialize(data = {})
-    #       @data = data
-    #     end
-    #
-    #     def read_attribute_for_serialization(key)
-    #       @data[key]
-    #     end
-    #   end
-    #
-    alias :read_attribute_for_serialization :send
-
-    # Add associations specified via the <tt>:include</tt> option.
-    #
-    # Expects a block that takes as arguments:
-    #   +association+ - name of the association
-    #   +records+     - the association record(s) to be serialized
-    #   +opts+        - options for the association records
-    def serializable_add_includes(options = {}) #:nodoc:
-      return unless include = options[:include]
-
-      unless include.is_a?(Hash)
-        include = Hash[Array.wrap(include).map { |n| n.is_a?(Hash) ? n.to_a.first : [n, {}] }]
-      end
-
-      include.each do |association, opts|
-        if records = send(association)
-          yield association, records, opts
-        end
-      end
-    end
-  end
-end
diff --git a/activemodel/lib/active_model/serializable/json.rb b/activemodel/lib/active_model/serializable/json.rb
deleted file mode 100644
index 79173929e4..0000000000
--- a/activemodel/lib/active_model/serializable/json.rb
+++ /dev/null
@@ -1,108 +0,0 @@
-require 'active_support/json'
-require 'active_support/core_ext/class/attribute'
-
-module ActiveModel
-  # == Active Model Serializable as JSON
-  module Serializable
-    module JSON
-      extend ActiveSupport::Concern
-      include ActiveModel::Serializable
-
-      included do
-        extend ActiveModel::Naming
-
-        class_attribute :include_root_in_json
-        self.include_root_in_json = true
-      end
-
-      # Returns a hash representing the model. Some configuration can be
-      # passed through +options+.
-      #
-      # The option <tt>include_root_in_json</tt> controls the top-level behavior
-      # of +as_json+. If true (the default) +as_json+ will emit a single root
-      # node named after the object's type. For example:
-      #
-      #   user = User.find(1)
-      #   user.as_json
-      #   # => { "user": {"id": 1, "name": "Konata Izumi", "age": 16,
-      #                   "created_at": "2006/08/01", "awesome": true} }
-      #
-      #   ActiveRecord::Base.include_root_in_json = false
-      #   user.as_json
-      #   # => {"id": 1, "name": "Konata Izumi", "age": 16,
-      #         "created_at": "2006/08/01", "awesome": true}
-      #
-      # This behavior can also be achieved by setting the <tt>:root</tt> option to +false+ as in:
-      #
-      #   user = User.find(1)
-      #   user.as_json(root: false)
-      #   # =>  {"id": 1, "name": "Konata Izumi", "age": 16,
-      #          "created_at": "2006/08/01", "awesome": true}
-      #
-      # The remainder of the examples in this section assume include_root_in_json is set to
-      # <tt>false</tt>.
-      #
-      # Without any +options+, the returned Hash will include all the model's
-      # attributes. For example:
-      #
-      #   user = User.find(1)
-      #   user.as_json
-      #   # => {"id": 1, "name": "Konata Izumi", "age": 16,
-      #         "created_at": "2006/08/01", "awesome": true}
-      #
-      # The <tt>:only</tt> and <tt>:except</tt> options can be used to limit the attributes
-      # included, and work similar to the +attributes+ method. For example:
-      #
-      #   user.as_json(:only => [ :id, :name ])
-      #   # => {"id": 1, "name": "Konata Izumi"}
-      #
-      #   user.as_json(:except => [ :id, :created_at, :age ])
-      #   # => {"name": "Konata Izumi", "awesome": true}
-      #
-      # To include the result of some method calls on the model use <tt>:methods</tt>:
-      #
-      #   user.as_json(:methods => :permalink)
-      #   # => {"id": 1, "name": "Konata Izumi", "age": 16,
-      #         "created_at": "2006/08/01", "awesome": true,
-      #         "permalink": "1-konata-izumi"}
-      #
-      # To include associations use <tt>:include</tt>:
-      #
-      #   user.as_json(:include => :posts)
-      #   # => {"id": 1, "name": "Konata Izumi", "age": 16,
-      #         "created_at": "2006/08/01", "awesome": true,
-      #         "posts": [{"id": 1, "author_id": 1, "title": "Welcome to the weblog"},
-      #                   {"id": 2, author_id: 1, "title": "So I was thinking"}]}
-      #
-      # Second level and higher order associations work as well:
-      #
-      #   user.as_json(:include => { :posts => {
-      #                                  :include => { :comments => {
-      #                                                :only => :body } },
-      #                                  :only => :title } })
-      #   # => {"id": 1, "name": "Konata Izumi", "age": 16,
-      #         "created_at": "2006/08/01", "awesome": true,
-      #         "posts": [{"comments": [{"body": "1st post!"}, {"body": "Second!"}],
-      #                    "title": "Welcome to the weblog"},
-      #                   {"comments": [{"body": "Don't think too hard"}],
-      #                    "title": "So I was thinking"}]}
-      def as_json(options = nil)
-        root = include_root_in_json
-        root = options[:root] if options.try(:key?, :root)
-        if root
-          root = self.class.model_name.element if root == true
-          { root => serializable_hash(options) }
-        else
-          serializable_hash(options)
-        end
-      end
-
-      def from_json(json, include_root=include_root_in_json)
-        hash = ActiveSupport::JSON.decode(json)
-        hash = hash.values.first if include_root
-        self.attributes = hash
-        self
-      end
-    end
-  end
-end
diff --git a/activemodel/lib/active_model/serializable/xml.rb b/activemodel/lib/active_model/serializable/xml.rb
deleted file mode 100644
index d11cee9b42..0000000000
--- a/activemodel/lib/active_model/serializable/xml.rb
+++ /dev/null
@@ -1,195 +0,0 @@
-require 'active_support/core_ext/array/wrap'
-require 'active_support/core_ext/class/attribute_accessors'
-require 'active_support/core_ext/array/conversions'
-require 'active_support/core_ext/hash/conversions'
-require 'active_support/core_ext/hash/slice'
-
-module ActiveModel
-  # == Active Model Serializable as XML
-  module Serializable
-    module XML
-      extend ActiveSupport::Concern
-      include ActiveModel::Serializable
-
-      class Serializer #:nodoc:
-        class Attribute #:nodoc:
-          attr_reader :name, :value, :type
-
-          def initialize(name, serializable, value)
-            @name, @serializable = name, serializable
-            value  = value.in_time_zone if value.respond_to?(:in_time_zone)
-            @value = value
-            @type  = compute_type
-          end
-
-          def decorations
-            decorations = {}
-            decorations[:encoding] = 'base64' if type == :binary
-            decorations[:type] = (type == :string) ? nil : type
-            decorations[:nil] = true if value.nil?
-            decorations
-          end
-
-        protected
-
-          def compute_type
-            return if value.nil?
-            type = ActiveSupport::XmlMini::TYPE_NAMES[value.class.name]
-            type ||= :string if value.respond_to?(:to_str)
-            type ||= :yaml
-            type
-          end
-        end
-
-        class MethodAttribute < Attribute #:nodoc:
-        end
-
-        attr_reader :options
-
-        def initialize(serializable, options = nil)
-          @serializable = serializable
-          @options = options ? options.dup : {}
-        end
-
-        def serializable_hash
-          @serializable.serializable_hash(@options.except(:include))
-        end
-
-        def serializable_collection
-          methods = Array.wrap(options[:methods]).map(&:to_s)
-          serializable_hash.map do |name, value|
-            name = name.to_s
-            if methods.include?(name)
-              self.class::MethodAttribute.new(name, @serializable, value)
-            else
-              self.class::Attribute.new(name, @serializable, value)
-            end
-          end
-        end
-
-        def serialize
-          require 'builder' unless defined? ::Builder
-
-          options[:indent]  ||= 2
-          options[:builder] ||= ::Builder::XmlMarkup.new(:indent => options[:indent])
-
-          @builder = options[:builder]
-          @builder.instruct! unless options[:skip_instruct]
-
-          root = (options[:root] || @serializable.class.model_name.element).to_s
-          root = ActiveSupport::XmlMini.rename_key(root, options)
-
-          args = [root]
-          args << {:xmlns => options[:namespace]} if options[:namespace]
-          args << {:type => options[:type]} if options[:type] && !options[:skip_types]
-
-          @builder.tag!(*args) do
-            add_attributes_and_methods
-            add_includes
-            add_extra_behavior
-            add_procs
-            yield @builder if block_given?
-          end
-        end
-
-      private
-
-        def add_extra_behavior
-        end
-
-        def add_attributes_and_methods
-          serializable_collection.each do |attribute|
-            key = ActiveSupport::XmlMini.rename_key(attribute.name, options)
-            ActiveSupport::XmlMini.to_tag(key, attribute.value,
-              options.merge(attribute.decorations))
-          end
-        end
-
-        def add_includes
-          @serializable.send(:serializable_add_includes, options) do |association, records, opts|
-            add_associations(association, records, opts)
-          end
-        end
-
-        # TODO This can likely be cleaned up to simple use ActiveSupport::XmlMini.to_tag as well.
-        def add_associations(association, records, opts)
-          merged_options = opts.merge(options.slice(:builder, :indent))
-          merged_options[:skip_instruct] = true
-
-          if records.is_a?(Enumerable)
-            tag  = ActiveSupport::XmlMini.rename_key(association.to_s, options)
-            type = options[:skip_types] ? { } : {:type => "array"}
-            association_name = association.to_s.singularize
-            merged_options[:root] = association_name
-
-            if records.empty?
-              @builder.tag!(tag, type)
-            else
-              @builder.tag!(tag, type) do
-                records.each do |record|
-                  if options[:skip_types]
-                    record_type = {}
-                  else
-                    record_class = (record.class.to_s.underscore == association_name) ? nil : record.class.name
-                    record_type = {:type => record_class}
-                  end
-
-                  record.to_xml merged_options.merge(record_type)
-                end
-              end
-            end
-          else
-            merged_options[:root] = association.to_s
-            records.to_xml(merged_options)
-          end
-        end
-
-        def add_procs
-          if procs = options.delete(:procs)
-            Array.wrap(procs).each do |proc|
-              if proc.arity == 1
-                proc.call(options)
-              else
-                proc.call(options, @serializable)
-              end
-            end
-          end
-        end
-      end
-
-      # Returns XML representing the model. Configuration can be
-      # passed through +options+.
-      #
-      # Without any +options+, the returned XML string will include all the model's
-      # attributes. For example:
-      #
-      #   user = User.find(1)
-      #   user.to_xml
-      #
-      #   <?xml version="1.0" encoding="UTF-8"?>
-      #   <user>
-      #     <id type="integer">1</id>
-      #     <name>David</name>
-      #     <age type="integer">16</age>
-      #     <created-at type="datetime">2011-01-30T22:29:23Z</created-at>
-      #   </user>
-      #
-      # The <tt>:only</tt> and <tt>:except</tt> options can be used to limit the attributes
-      # included, and work similar to the +attributes+ method.
-      #
-      # To include the result of some method calls on the model use <tt>:methods</tt>.
-      #
-      # To include associations use <tt>:include</tt>.
-      #
-      # For further documentation see activerecord/lib/active_record/serializers/xml_serializer.xml.
-      def to_xml(options = {}, &block)
-        Serializer.new(self, options).serialize(&block)
-      end
-
-      def from_xml(xml)
-        self.attributes = Hash.from_xml(xml).values.first
-        self
-      end
-    end
-  end
-end
diff --git a/activemodel/lib/active_model/serialization.rb b/activemodel/lib/active_model/serialization.rb
index 439302c632..a4b58ab456 100644
--- a/activemodel/lib/active_model/serialization.rb
+++ b/activemodel/lib/active_model/serialization.rb
@@ -1,10 +1,139 @@
+require 'active_support/core_ext/hash/except'
+require 'active_support/core_ext/hash/slice'
+require 'active_support/core_ext/array/wrap'
+
+
 module ActiveModel
+  # == Active Model Serialization
+  #
+  # Provides a basic serialization to a serializable_hash for your object.
+  #
+  # A minimal implementation could be:
+  #
+  #   class Person
+  #
+  #     include ActiveModel::Serialization
+  #
+  #     attr_accessor :name
+  #
+  #     def attributes
+  #       {'name' => name}
+  #     end
+  #
+  #   end
+  #
+  # Which would provide you with:
+  #
+  #   person = Person.new
+  #   person.serializable_hash   # => {"name"=>nil}
+  #   person.name = "Bob"
+  #   person.serializable_hash   # => {"name"=>"Bob"}
+  #
+  # You need to declare some sort of attributes hash which contains the attributes
+  # you want to serialize and their current value.
+  #
+  # Most of the time though, you will want to include the JSON or XML
+  # serializations. Both of these modules automatically include the
+  # ActiveModel::Serialization module, so there is no need to explicitly
+  # include it.
+  #
+  # So a minimal implementation including XML and JSON would be:
+  #
+  #   class Person
+  #
+  #     include ActiveModel::Serializers::JSON
+  #     include ActiveModel::Serializers::Xml
+  #
+  #     attr_accessor :name
+  #
+  #     def attributes
+  #       {'name' => name}
+  #     end
+  #
+  #   end
+  #
+  # Which would provide you with:
+  #
+  #   person = Person.new
+  #   person.serializable_hash   # => {"name"=>nil}
+  #   person.as_json             # => {"name"=>nil}
+  #   person.to_json             # => "{\"name\":null}"
+  #   person.to_xml              # => "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<serial-person...
+  #
+  #   person.name = "Bob"
+  #   person.serializable_hash   # => {"name"=>"Bob"}
+  #   person.as_json             # => {"name"=>"Bob"}
+  #   person.to_json             # => "{\"name\":\"Bob\"}"
+  #   person.to_xml              # => "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<serial-person...
+  #
+  # Valid options are <tt>:only</tt>, <tt>:except</tt> and <tt>:methods</tt> .
   module Serialization
-    extend ActiveSupport::Concern
-    include ActiveModel::Serializable
+    def serializable_hash(options = nil)
+      options ||= {}
+
+      attribute_names = attributes.keys.sort
+      if only = options[:only]
+        attribute_names &= Array.wrap(only).map(&:to_s)
+      elsif except = options[:except]
+        attribute_names -= Array.wrap(except).map(&:to_s)
+      end
+
+      hash = {}
+      attribute_names.each { |n| hash[n] = read_attribute_for_serialization(n) }
+
+      method_names = Array.wrap(options[:methods]).select { |n| respond_to?(n) }
+      method_names.each { |n| hash[n] = send(n) }
+
+      serializable_add_includes(options) do |association, records, opts|
+        hash[association] = if records.is_a?(Enumerable)
+          records.map { |a| a.serializable_hash(opts) }
+        else
+          records.serializable_hash(opts)
+        end
+      end
 
-    included do
-      ActiveSupport::Deprecation.warn "ActiveModel::Serialization is deprecated in favor of ActiveModel::Serializable"
+      hash
     end
+
+    private
+
+      # Hook method defining how an attribute value should be retrieved for
+      # serialization. By default this is assumed to be an instance named after
+      # the attribute. Override this method in subclasses should you need to
+      # retrieve the value for a given attribute differently:
+      #
+      #   class MyClass
+      #     include ActiveModel::Validations
+      #
+      #     def initialize(data = {})
+      #       @data = data
+      #     end
+      #
+      #     def read_attribute_for_serialization(key)
+      #       @data[key]
+      #     end
+      #   end
+      #
+      alias :read_attribute_for_serialization :send
+
+      # Add associations specified via the <tt>:include</tt> option.
+      #
+      # Expects a block that takes as arguments:
+      #   +association+ - name of the association
+      #   +records+     - the association record(s) to be serialized
+      #   +opts+        - options for the association records
+      def serializable_add_includes(options = {}) #:nodoc:
+        return unless include = options[:include]
+
+        unless include.is_a?(Hash)
+          include = Hash[Array.wrap(include).map { |n| n.is_a?(Hash) ? n.to_a.first : [n, {}] }]
+        end
+
+        include.each do |association, opts|
+          if records = send(association)
+            yield association, records, opts
+          end
+        end
+      end
   end
-end
\ No newline at end of file
+end
diff --git a/activemodel/lib/active_model/serializer.rb b/activemodel/lib/active_model/serializer.rb
deleted file mode 100644
index 0e23df2f2b..0000000000
--- a/activemodel/lib/active_model/serializer.rb
+++ /dev/null
@@ -1,253 +0,0 @@
-require "active_support/core_ext/class/attribute"
-require "active_support/core_ext/string/inflections"
-require "active_support/core_ext/module/anonymous"
-require "set"
-
-module ActiveModel
-  # Active Model Array Serializer
-  #
-  # It serializes an array checking if each element that implements
-  # the +active_model_serializer+ method passing down the current scope.
-  class ArraySerializer
-    attr_reader :object, :scope
-
-    def initialize(object, scope)
-      @object, @scope = object, scope
-    end
-
-    def serializable_array
-      @object.map do |item|
-        if item.respond_to?(:active_model_serializer) && (serializer = item.active_model_serializer)
-          serializer.new(item, scope)
-        else
-          item
-        end
-      end
-    end
-
-    def as_json(*args)
-      serializable_array.as_json(*args)
-    end
-  end
-
-  # Active Model Serializer
-  #
-  # Provides a basic serializer implementation that allows you to easily
-  # control how a given object is going to be serialized. On initialization,
-  # it expects to object as arguments, a resource and a scope. For example,
-  # one may do in a controller:
-  #
-  #     PostSerializer.new(@post, current_user).to_json
-  #
-  # The object to be serialized is the +@post+ and the scope is +current_user+.
-  #
-  # We use the scope to check if a given attribute should be serialized or not.
-  # For example, some attributes maybe only be returned if +current_user+ is the
-  # author of the post:
-  #
-  #     class PostSerializer < ActiveModel::Serializer
-  #       attributes :title, :body
-  #       has_many :comments
-  #     
-  #       private
-  #
-  #       def attributes
-  #         hash = super
-  #         hash.merge!(:email => post.email) if author?
-  #         hash
-  #       end
-  #     
-  #       def author?
-  #         post.author == scope
-  #       end
-  #     end
-  #
-  class Serializer
-    module Associations #:nodoc:
-      class Config < Struct.new(:name, :options) #:nodoc:
-        def serializer
-          options[:serializer]
-        end
-      end
-
-      class HasMany < Config #:nodoc:
-        def serialize(collection, scope)
-          collection.map do |item|
-            serializer.new(item, scope).serializable_hash
-          end
-        end
-
-        def serialize_ids(collection, scope)
-          # use named scopes if they are present
-          # return collection.ids if collection.respond_to?(:ids)
-
-          collection.map do |item|
-            item.read_attribute_for_serialization(:id)
-          end
-        end
-      end
-
-      class HasOne < Config #:nodoc:
-        def serialize(object, scope)
-          object && serializer.new(object, scope).serializable_hash
-        end
-
-        def serialize_ids(object, scope)
-          object && object.read_attribute_for_serialization(:id)
-        end
-      end
-    end
-
-    class_attribute :_attributes
-    self._attributes = Set.new
-
-    class_attribute :_associations
-    self._associations = []
-
-    class_attribute :_root
-    class_attribute :_embed
-    self._embed = :objects
-    class_attribute :_root_embed
-
-    class << self
-      # Define attributes to be used in the serialization.
-      def attributes(*attrs)
-        self._attributes += attrs
-      end
-
-      def associate(klass, attrs) #:nodoc:
-        options = attrs.extract_options!
-        self._associations += attrs.map do |attr|
-          unless method_defined?(attr)
-            class_eval "def #{attr}() object.#{attr} end", __FILE__, __LINE__
-          end
-
-          options[:serializer] ||= const_get("#{attr.to_s.camelize}Serializer")
-          klass.new(attr, options)
-        end
-      end
-
-      # Defines an association in the object should be rendered.
-      #
-      # The serializer object should implement the association name
-      # as a method which should return an array when invoked. If a method
-      # with the association name does not exist, the association name is
-      # dispatched to the serialized object.
-      def has_many(*attrs)
-        associate(Associations::HasMany, attrs)
-      end
-
-      # Defines an association in the object should be rendered.
-      #
-      # The serializer object should implement the association name
-      # as a method which should return an object when invoked. If a method
-      # with the association name does not exist, the association name is
-      # dispatched to the serialized object.
-      def has_one(*attrs)
-        associate(Associations::HasOne, attrs)
-      end
-
-      # Define how associations should be embedded.
-      #
-      #   embed :objects               # Embed associations as full objects
-      #   embed :ids                   # Embed only the association ids
-      #   embed :ids, :include => true # Embed the association ids and include objects in the root
-      #
-      def embed(type, options={})
-        self._embed = type
-        self._root_embed = true if options[:include]
-      end
-
-      # Defines the root used on serialization. If false, disables the root.
-      def root(name)
-        self._root = name
-      end
-
-      def inherited(klass) #:nodoc:
-        return if klass.anonymous?
-
-        name = klass.name.demodulize.underscore.sub(/_serializer$/, '')
-
-        klass.class_eval do
-          alias_method name.to_sym, :object
-          root name.to_sym unless self._root == false
-        end
-      end
-    end
-
-    attr_reader :object, :scope
-
-    def initialize(object, scope)
-      @object, @scope = object, scope
-    end
-
-    # Returns a json representation of the serializable
-    # object including the root.
-    def as_json(*)
-      if _root
-        hash = { _root => serializable_hash }
-        hash.merge!(associations) if _root_embed
-        hash
-      else
-        serializable_hash
-      end
-    end
-
-    # Returns a hash representation of the serializable
-    # object without the root.
-    def serializable_hash
-      if _embed == :ids
-        attributes.merge(association_ids)
-      elsif _embed == :objects
-        attributes.merge(associations)
-      else
-        attributes
-      end
-    end
-
-    # Returns a hash representation of the serializable
-    # object associations.
-    def associations
-      hash = {}
-
-      _associations.each do |association|
-        associated_object = send(association.name)
-        hash[association.name] = association.serialize(associated_object, scope)
-      end
-
-      hash
-    end
-
-    # Returns a hash representation of the serializable
-    # object associations ids.
-    def association_ids
-      hash = {}
-
-      _associations.each do |association|
-        associated_object = send(association.name)
-        hash[association.name] = association.serialize_ids(associated_object, scope)
-      end
-
-      hash
-    end
-
-    # Returns a hash representation of the serializable
-    # object attributes.
-    def attributes
-      hash = {}
-
-      _attributes.each do |name|
-        hash[name] = @object.read_attribute_for_serialization(name)
-      end
-
-      hash
-    end
-  end
-end
-
-class Array
-  # Array uses ActiveModel::ArraySerializer.
-  def active_model_serializer
-    ActiveModel::ArraySerializer
-  end
-end
\ No newline at end of file
diff --git a/activemodel/lib/active_model/serializers/json.rb b/activemodel/lib/active_model/serializers/json.rb
index 9efd7c5f69..c845440120 100644
--- a/activemodel/lib/active_model/serializers/json.rb
+++ b/activemodel/lib/active_model/serializers/json.rb
@@ -1,12 +1,108 @@
+require 'active_support/json'
+require 'active_support/core_ext/class/attribute'
+
 module ActiveModel
+  # == Active Model JSON Serializer
   module Serializers
     module JSON
       extend ActiveSupport::Concern
-      include ActiveModel::Serializable::JSON
+      include ActiveModel::Serialization
 
       included do
-        ActiveSupport::Deprecation.warn "ActiveModel::Serializers::JSON is deprecated in favor of ActiveModel::Serializable::JSON"
+        extend ActiveModel::Naming
+
+        class_attribute :include_root_in_json
+        self.include_root_in_json = true
+      end
+
+      # Returns a hash representing the model. Some configuration can be
+      # passed through +options+.
+      #
+      # The option <tt>include_root_in_json</tt> controls the top-level behavior
+      # of +as_json+. If true (the default) +as_json+ will emit a single root
+      # node named after the object's type. For example:
+      #
+      #   user = User.find(1)
+      #   user.as_json
+      #   # => { "user": {"id": 1, "name": "Konata Izumi", "age": 16,
+      #                   "created_at": "2006/08/01", "awesome": true} }
+      #
+      #   ActiveRecord::Base.include_root_in_json = false
+      #   user.as_json
+      #   # => {"id": 1, "name": "Konata Izumi", "age": 16,
+      #         "created_at": "2006/08/01", "awesome": true}
+      #
+      # This behavior can also be achieved by setting the <tt>:root</tt> option to +false+ as in:
+      #
+      #   user = User.find(1)
+      #   user.as_json(root: false)
+      #   # =>  {"id": 1, "name": "Konata Izumi", "age": 16,
+      #          "created_at": "2006/08/01", "awesome": true}
+      #
+      # The remainder of the examples in this section assume include_root_in_json is set to
+      # <tt>false</tt>.
+      #
+      # Without any +options+, the returned Hash will include all the model's
+      # attributes. For example:
+      #
+      #   user = User.find(1)
+      #   user.as_json
+      #   # => {"id": 1, "name": "Konata Izumi", "age": 16,
+      #         "created_at": "2006/08/01", "awesome": true}
+      #
+      # The <tt>:only</tt> and <tt>:except</tt> options can be used to limit the attributes
+      # included, and work similar to the +attributes+ method. For example:
+      #
+      #   user.as_json(:only => [ :id, :name ])
+      #   # => {"id": 1, "name": "Konata Izumi"}
+      #
+      #   user.as_json(:except => [ :id, :created_at, :age ])
+      #   # => {"name": "Konata Izumi", "awesome": true}
+      #
+      # To include the result of some method calls on the model use <tt>:methods</tt>:
+      #
+      #   user.as_json(:methods => :permalink)
+      #   # => {"id": 1, "name": "Konata Izumi", "age": 16,
+      #         "created_at": "2006/08/01", "awesome": true,
+      #         "permalink": "1-konata-izumi"}
+      #
+      # To include associations use <tt>:include</tt>:
+      #
+      #   user.as_json(:include => :posts)
+      #   # => {"id": 1, "name": "Konata Izumi", "age": 16,
+      #         "created_at": "2006/08/01", "awesome": true,
+      #         "posts": [{"id": 1, "author_id": 1, "title": "Welcome to the weblog"},
+      #                   {"id": 2, author_id: 1, "title": "So I was thinking"}]}
+      #
+      # Second level and higher order associations work as well:
+      #
+      #   user.as_json(:include => { :posts => {
+      #                                  :include => { :comments => {
+      #                                                :only => :body } },
+      #                                  :only => :title } })
+      #   # => {"id": 1, "name": "Konata Izumi", "age": 16,
+      #         "created_at": "2006/08/01", "awesome": true,
+      #         "posts": [{"comments": [{"body": "1st post!"}, {"body": "Second!"}],
+      #                    "title": "Welcome to the weblog"},
+      #                   {"comments": [{"body": "Don't think too hard"}],
+      #                    "title": "So I was thinking"}]}
+      def as_json(options = nil)
+        root = include_root_in_json
+        root = options[:root] if options.try(:key?, :root)
+        if root
+          root = self.class.model_name.element if root == true
+          { root => serializable_hash(options) }
+        else
+          serializable_hash(options)
+        end
+      end
+
+      def from_json(json, include_root=include_root_in_json)
+        hash = ActiveSupport::JSON.decode(json)
+        hash = hash.values.first if include_root
+        self.attributes = hash
+        self
       end
     end
   end
-end
\ No newline at end of file
+end
diff --git a/activemodel/lib/active_model/serializers/xml.rb b/activemodel/lib/active_model/serializers/xml.rb
index 620390da6b..d61d9d7119 100644
--- a/activemodel/lib/active_model/serializers/xml.rb
+++ b/activemodel/lib/active_model/serializers/xml.rb
@@ -1,14 +1,195 @@
+require 'active_support/core_ext/array/wrap'
+require 'active_support/core_ext/class/attribute_accessors'
+require 'active_support/core_ext/array/conversions'
+require 'active_support/core_ext/hash/conversions'
+require 'active_support/core_ext/hash/slice'
+
 module ActiveModel
+  # == Active Model XML Serializer
   module Serializers
     module Xml
       extend ActiveSupport::Concern
-      include ActiveModel::Serializable::XML
+      include ActiveModel::Serialization
+
+      class Serializer #:nodoc:
+        class Attribute #:nodoc:
+          attr_reader :name, :value, :type
+
+          def initialize(name, serializable, value)
+            @name, @serializable = name, serializable
+            value  = value.in_time_zone if value.respond_to?(:in_time_zone)
+            @value = value
+            @type  = compute_type
+          end
+
+          def decorations
+            decorations = {}
+            decorations[:encoding] = 'base64' if type == :binary
+            decorations[:type] = (type == :string) ? nil : type
+            decorations[:nil] = true if value.nil?
+            decorations
+          end
+
+        protected
+
+          def compute_type
+            return if value.nil?
+            type = ActiveSupport::XmlMini::TYPE_NAMES[value.class.name]
+            type ||= :string if value.respond_to?(:to_str)
+            type ||= :yaml
+            type
+          end
+        end
+
+        class MethodAttribute < Attribute #:nodoc:
+        end
+
+        attr_reader :options
+
+        def initialize(serializable, options = nil)
+          @serializable = serializable
+          @options = options ? options.dup : {}
+        end
+
+        def serializable_hash
+          @serializable.serializable_hash(@options.except(:include))
+        end
+
+        def serializable_collection
+          methods = Array.wrap(options[:methods]).map(&:to_s)
+          serializable_hash.map do |name, value|
+            name = name.to_s
+            if methods.include?(name)
+              self.class::MethodAttribute.new(name, @serializable, value)
+            else
+              self.class::Attribute.new(name, @serializable, value)
+            end
+          end
+        end
+
+        def serialize
+          require 'builder' unless defined? ::Builder
+
+          options[:indent]  ||= 2
+          options[:builder] ||= ::Builder::XmlMarkup.new(:indent => options[:indent])
+
+          @builder = options[:builder]
+          @builder.instruct! unless options[:skip_instruct]
 
-      Serializer = ActiveModel::Serializable::XML::Serializer
+          root = (options[:root] || @serializable.class.model_name.element).to_s
+          root = ActiveSupport::XmlMini.rename_key(root, options)
+
+          args = [root]
+          args << {:xmlns => options[:namespace]} if options[:namespace]
+          args << {:type => options[:type]} if options[:type] && !options[:skip_types]
+
+          @builder.tag!(*args) do
+            add_attributes_and_methods
+            add_includes
+            add_extra_behavior
+            add_procs
+            yield @builder if block_given?
+          end
+        end
+
+      private
+
+        def add_extra_behavior
+        end
+
+        def add_attributes_and_methods
+          serializable_collection.each do |attribute|
+            key = ActiveSupport::XmlMini.rename_key(attribute.name, options)
+            ActiveSupport::XmlMini.to_tag(key, attribute.value,
+              options.merge(attribute.decorations))
+          end
+        end
+
+        def add_includes
+          @serializable.send(:serializable_add_includes, options) do |association, records, opts|
+            add_associations(association, records, opts)
+          end
+        end
+
+        # TODO This can likely be cleaned up to simple use ActiveSupport::XmlMini.to_tag as well.
+        def add_associations(association, records, opts)
+          merged_options = opts.merge(options.slice(:builder, :indent))
+          merged_options[:skip_instruct] = true
+
+          if records.is_a?(Enumerable)
+            tag  = ActiveSupport::XmlMini.rename_key(association.to_s, options)
+            type = options[:skip_types] ? { } : {:type => "array"}
+            association_name = association.to_s.singularize
+            merged_options[:root] = association_name
+
+            if records.empty?
+              @builder.tag!(tag, type)
+            else
+              @builder.tag!(tag, type) do
+                records.each do |record|
+                  if options[:skip_types]
+                    record_type = {}
+                  else
+                    record_class = (record.class.to_s.underscore == association_name) ? nil : record.class.name
+                    record_type = {:type => record_class}
+                  end
+
+                  record.to_xml merged_options.merge(record_type)
+                end
+              end
+            end
+          else
+            merged_options[:root] = association.to_s
+            records.to_xml(merged_options)
+          end
+        end
+
+        def add_procs
+          if procs = options.delete(:procs)
+            Array.wrap(procs).each do |proc|
+              if proc.arity == 1
+                proc.call(options)
+              else
+                proc.call(options, @serializable)
+              end
+            end
+          end
+        end
+      end
+
+      # Returns XML representing the model. Configuration can be
+      # passed through +options+.
+      #
+      # Without any +options+, the returned XML string will include all the model's
+      # attributes. For example:
+      #
+      #   user = User.find(1)
+      #   user.to_xml
+      #
+      #   <?xml version="1.0" encoding="UTF-8"?>
+      #   <user>
+      #     <id type="integer">1</id>
+      #     <name>David</name>
+      #     <age type="integer">16</age>
+      #     <created-at type="datetime">2011-01-30T22:29:23Z</created-at>
+      #   </user>
+      #
+      # The <tt>:only</tt> and <tt>:except</tt> options can be used to limit the attributes
+      # included, and work similar to the +attributes+ method.
+      #
+      # To include the result of some method calls on the model use <tt>:methods</tt>.
+      #
+      # To include associations use <tt>:include</tt>.
+      #
+      # For further documentation see activerecord/lib/active_record/serializers/xml_serializer.xml.
+      def to_xml(options = {}, &block)
+        Serializer.new(self, options).serialize(&block)
+      end
 
-      included do
-        ActiveSupport::Deprecation.warn "ActiveModel::Serializers::Xml is deprecated in favor of ActiveModel::Serializable::XML"
+      def from_xml(xml)
+        self.attributes = Hash.from_xml(xml).values.first
+        self
       end
     end
   end
-end
\ No newline at end of file
+end
-- 
cgit v1.2.3