I was profiling my application and noticed that serialized
attributes are encoded into yaml twice. The reason is that
ActiveRecord::Base#create is calling #quoted_column_names without
specifying quoted attributes that it already calculated, which
causes the second call to #attributes_with_quotes, which encodes
serialized attributes into yaml. I have noticed it because I have a
large hash in that attribute, which takes 3+ seconds to
#to_yaml.
This is in Rails 2.3.5. I haven't looked into the older
versions.
My fix for it was to monkey patch AR:Base with:
def create_without_timestamps
if self.id.nil? && connection.prefetch_primary_key?(self.class.table_name)
self.id = connection.next_sequence_value(self.class.sequence_name)
end
quoted_attributes = attributes_with_quotes
statement = if quoted_attributes.empty?
connection.empty_insert_statement(self.class.table_name)
else
"INSERT INTO #{self.class.quoted_table_name} " +
#"(#{quoted_column_names.join(', ')}) " + # original
"(#{quoted_column_names(quoted_attributes).join(', ')}) " + # providing an existing set of attributes to avoid performance penalty
"VALUES(#{quoted_attributes.values.join(', ')})"
end
self.id = connection.insert(statement, "#{self.class.name} Create",
self.class.primary_key, self.id, self.class.sequence_name)
@new_record = false
id
end