summaryrefslogtreecommitdiffhomepage
path: root/lib/axlsx/util/serialized_attributes.rb
diff options
context:
space:
mode:
authorPaul Kmiec <[email protected]>2023-04-29 16:24:22 -0700
committerPaul Kmiec <[email protected]>2023-05-15 23:36:40 -0700
commita4ba108eb33cba35f87370b7e4b47bff18130e89 (patch)
tree3ed38268770453feb0dca6407e4b42c94894f02a /lib/axlsx/util/serialized_attributes.rb
parent3b9ac17d8e4dc8b315ac307ffad6f2aa0cb96741 (diff)
downloadcaxlsx-a4ba108eb33cba35f87370b7e4b47bff18130e89.tar.gz
caxlsx-a4ba108eb33cba35f87370b7e4b47bff18130e89.zip
Serialize attributes more efficiently
The attributes in rows, cells, styles, etc are pre-defined for each type and almost never change. The current code, however, does not take that into account by reading all instance variables (via declared_attributes), filtering out the blank one and ones that are not xml attributes, and by camelizing each one. We can avoid all this extra work by computing the camels and ivars for xml attributes once and directly read the instance variables we care about.
Diffstat (limited to 'lib/axlsx/util/serialized_attributes.rb')
-rw-r--r--lib/axlsx/util/serialized_attributes.rb53
1 files changed, 38 insertions, 15 deletions
diff --git a/lib/axlsx/util/serialized_attributes.rb b/lib/axlsx/util/serialized_attributes.rb
index b7247e0d..b2b63fe1 100644
--- a/lib/axlsx/util/serialized_attributes.rb
+++ b/lib/axlsx/util/serialized_attributes.rb
@@ -15,11 +15,21 @@ module Axlsx
# which of the instance values are serializable
def serializable_attributes(*symbols)
@xml_attributes = symbols
+ @camel_xml_attributes = nil
+ @ivar_xml_attributes = nil
end
# a reader for those attributes
attr_reader :xml_attributes
+ def camel_xml_attributes
+ @camel_xml_attributes ||= @xml_attributes.map { |attr| Axlsx.camel(attr, false) }
+ end
+
+ def ivar_xml_attributes
+ @ivar_xml_attributes ||= @xml_attributes.map { |attr| :"@#{attr}" }
+ end
+
# This helper registers the attributes that will be formatted as elements.
def serializable_element_attributes(*symbols)
@xml_element_attributes = symbols
@@ -32,12 +42,12 @@ module Axlsx
# creates a XML tag with serialized attributes
# @see SerializedAttributes#serialized_attributes
def serialized_tag(tagname, str, additional_attributes = {}, &block)
- str << "<#{tagname} "
+ str << '<' << tagname << ' '
serialized_attributes(str, additional_attributes)
if block_given?
str << '>'
yield
- str << "</#{tagname}>"
+ str << '</' << tagname << '>'
else
str << '/>'
end
@@ -49,21 +59,34 @@ module Axlsx
# serialization to.
# @param [Hash] additional_attributes An option key value hash for
# defining values that are not serializable attributes list.
- def serialized_attributes(str = +'', additional_attributes = {})
- attributes = declared_attributes.merge! additional_attributes
- attributes.each do |key, value|
- str << "#{Axlsx.camel(key, false)}=\"#{Axlsx.camel(Axlsx.booleanize(value), false)}\" "
+ # @param [Boolean] camelize_value Should the attribute values be camelized
+ def serialized_attributes(str = +'', additional_attributes = {}, camelize_value = true)
+ camel_xml_attributes = self.class.camel_xml_attributes
+ ivar_xml_attributes = self.class.ivar_xml_attributes
+
+ self.class.xml_attributes.each_with_index do |attr, index|
+ next if additional_attributes.key?(attr)
+ next unless instance_variable_defined?(ivar_xml_attributes[index])
+
+ value = instance_variable_get(ivar_xml_attributes[index])
+ next if value.nil?
+
+ value = Axlsx.booleanize(value)
+ value = Axlsx.camel(value, false) if camelize_value
+
+ str << camel_xml_attributes[index] << '="' << value.to_s << '" '
end
- str
- end
- # A hash of instance variables that have been declared with
- # seraialized_attributes and are not nil.
- # This requires ruby 1.9.3 or higher
- def declared_attributes
- Axlsx.instance_values_for(self).select do |key, value|
- value != nil && self.class.xml_attributes.include?(key.to_sym)
+ additional_attributes.each do |attr, value|
+ next if value.nil?
+
+ value = Axlsx.booleanize(value)
+ value = Axlsx.camel(value, false) if camelize_value
+
+ str << Axlsx.camel(attr, false) << '="' << value.to_s << '" '
end
+
+ str
end
# serialized instance values at text nodes on a camelized element of the
@@ -82,7 +105,7 @@ module Axlsx
value = yield value if block_given?
element_name = Axlsx.camel(attribute_name, false)
- str << "<#{element_name}>#{value}</#{element_name}>"
+ str << '<' << element_name << '>' << value << '</' << element_name << '>'
end
str
end