提交 9476daa8 编写于 作者: J José Valim

Speed up xml serializer by computing values just once and remove unecessary code duplication.

上级 81fb7424
require 'active_support/core_ext/array/wrap' require 'active_support/core_ext/array/wrap'
require 'active_support/core_ext/class/attribute_accessors' require 'active_support/core_ext/class/attribute_accessors'
require 'active_support/core_ext/hash/conversions' require 'active_support/core_ext/hash/conversions'
require 'active_support/core_ext/hash/slice'
module ActiveModel module ActiveModel
module Serializers module Serializers
...@@ -12,8 +13,10 @@ class Serializer #:nodoc: ...@@ -12,8 +13,10 @@ class Serializer #:nodoc:
class Attribute #:nodoc: class Attribute #:nodoc:
attr_reader :name, :value, :type attr_reader :name, :value, :type
def initialize(name, serializable) def initialize(name, serializable, raw_value=nil)
@name, @serializable = name, serializable @name, @serializable = name, serializable
@raw_value = raw_value || @serializable.send(name)
@type = compute_type @type = compute_type
@value = compute_value @value = compute_value
end end
...@@ -51,20 +54,17 @@ def decorations(include_types = true) ...@@ -51,20 +54,17 @@ def decorations(include_types = true)
protected protected
def compute_type def compute_type
value = @serializable.send(name) type = Hash::XML_TYPE_NAMES[@raw_value.class.name]
type = Hash::XML_TYPE_NAMES[value.class.name] type ||= :string if @raw_value.respond_to?(:to_str)
type ||= :string if value.respond_to?(:to_str)
type ||= :yaml type ||= :yaml
type type
end end
def compute_value def compute_value
value = @serializable.send(name)
if formatter = Hash::XML_FORMATTING[type.to_s] if formatter = Hash::XML_FORMATTING[type.to_s]
value ? formatter.call(value) : nil @raw_value ? formatter.call(@raw_value) : nil
else else
value @raw_value
end end
end end
end end
...@@ -72,7 +72,7 @@ def compute_value ...@@ -72,7 +72,7 @@ def compute_value
class MethodAttribute < Attribute #:nodoc: class MethodAttribute < Attribute #:nodoc:
protected protected
def compute_type def compute_type
Hash::XML_TYPE_NAMES[@serializable.send(name).class.name] || :string Hash::XML_TYPE_NAMES[@raw_value.class.name] || :string
end end
end end
...@@ -92,25 +92,24 @@ def initialize(serializable, options = nil) ...@@ -92,25 +92,24 @@ def initialize(serializable, options = nil)
# then because <tt>:except</tt> is set to a default value, the second # then because <tt>:except</tt> is set to a default value, the second
# level model can have both <tt>:except</tt> and <tt>:only</tt> set. So if # level model can have both <tt>:except</tt> and <tt>:only</tt> set. So if
# <tt>:only</tt> is set, always delete <tt>:except</tt>. # <tt>:only</tt> is set, always delete <tt>:except</tt>.
def serializable_attribute_names def serializable_attributes_hash
attribute_names = @serializable.attributes.keys.sort attributes = @serializable.attributes
if options[:only].any? if options[:only].any?
attribute_names &= options[:only] attributes.slice(*options[:only])
elsif options[:except].any? elsif options[:except].any?
attribute_names -= options[:except] attributes.except(*options[:except])
else
attributes
end end
attribute_names
end end
def serializable_attributes def serializable_attributes
serializable_attribute_names.collect { |name| Attribute.new(name, @serializable) } serializable_attributes_hash.map { |name, value| self.class::Attribute.new(name, @serializable, value) }
end end
def serializable_method_attributes def serializable_method_attributes
Array.wrap(options[:methods]).inject([]) do |methods, name| Array.wrap(options[:methods]).inject([]) do |methods, name|
methods << MethodAttribute.new(name.to_s, @serializable) if @serializable.respond_to?(name.to_s) methods << self.class::MethodAttribute.new(name.to_s, @serializable) if @serializable.respond_to?(name.to_s)
methods methods
end end
end end
......
...@@ -182,17 +182,6 @@ def initialize(*args) ...@@ -182,17 +182,6 @@ def initialize(*args)
options[:except] |= Array.wrap(@serializable.class.inheritance_column) options[:except] |= Array.wrap(@serializable.class.inheritance_column)
end end
def serializable_attributes
serializable_attribute_names.collect { |name| Attribute.new(name, @serializable) }
end
def serializable_method_attributes
Array.wrap(options[:methods]).inject([]) do |method_attributes, name|
method_attributes << MethodAttribute.new(name.to_s, @serializable) if @serializable.respond_to?(name.to_s)
method_attributes
end
end
def add_associations(association, records, opts) def add_associations(association, records, opts)
if records.is_a?(Enumerable) if records.is_a?(Enumerable)
tag = reformat_name(association.to_s) tag = reformat_name(association.to_s)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册