mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Merge pull request #33223 from rails/homogeneous-allocation
Speed up homogeneous AR lists / reduce allocations
This commit is contained in:
commit
316513177c
5 changed files with 49 additions and 2 deletions
|
@ -344,6 +344,28 @@ module ActiveRecord
|
|||
self
|
||||
end
|
||||
|
||||
##
|
||||
# Initializer used for instantiating objects that have been read from the
|
||||
# database. +attributes+ should be an attributes object, and unlike the
|
||||
# `initialize` method, no assignment calls are made per attribute.
|
||||
#
|
||||
# :nodoc:
|
||||
def init_from_db(attributes)
|
||||
init_internals
|
||||
|
||||
@new_record = false
|
||||
@attributes = attributes
|
||||
|
||||
self.class.define_attribute_methods
|
||||
|
||||
yield self if block_given?
|
||||
|
||||
_run_find_callbacks
|
||||
_run_initialize_callbacks
|
||||
|
||||
self
|
||||
end
|
||||
|
||||
##
|
||||
# :method: clone
|
||||
# Identical to Ruby's clone method. This is a "shallow" copy. Be warned that your attributes are not copied.
|
||||
|
|
|
@ -67,8 +67,18 @@ module ActiveRecord
|
|||
# how this "single-table" inheritance mapping is implemented.
|
||||
def instantiate(attributes, column_types = {}, &block)
|
||||
klass = discriminate_class_for_record(attributes)
|
||||
instantiate_instance_of(klass, attributes, column_types, &block)
|
||||
end
|
||||
|
||||
# Given a class, an attributes hash, +instantiate_instance_of+ returns a
|
||||
# new instance of the class. Accepts only keys as strings.
|
||||
#
|
||||
# This is private, don't call it. :)
|
||||
#
|
||||
# :nodoc:
|
||||
def instantiate_instance_of(klass, attributes, column_types = {}, &block)
|
||||
attributes = klass.attributes_builder.build_from_database(attributes, column_types)
|
||||
klass.allocate.init_with("attributes" => attributes, "new_record" => false, &block)
|
||||
klass.allocate.init_from_db(attributes, &block)
|
||||
end
|
||||
|
||||
# Updates an object (or multiple objects) and saves it to the database, if validations pass.
|
||||
|
|
|
@ -49,7 +49,12 @@ module ActiveRecord
|
|||
}
|
||||
|
||||
message_bus.instrument("instantiation.active_record", payload) do
|
||||
result_set.map { |record| instantiate(record, column_types, &block) }
|
||||
if result_set.includes_column?(inheritance_column)
|
||||
result_set.map { |record| instantiate(record, column_types, &block) }
|
||||
else
|
||||
# Instantiate a homogeneous set
|
||||
result_set.map { |record| instantiate_instance_of(self, record, column_types, &block) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -43,6 +43,11 @@ module ActiveRecord
|
|||
@column_types = column_types
|
||||
end
|
||||
|
||||
# Returns true if this result set includes the column named +name+
|
||||
def includes_column?(name)
|
||||
@columns.include? name
|
||||
end
|
||||
|
||||
# Returns the number of elements in the rows array.
|
||||
def length
|
||||
@rows.length
|
||||
|
|
|
@ -12,6 +12,11 @@ module ActiveRecord
|
|||
])
|
||||
end
|
||||
|
||||
test "includes_column?" do
|
||||
assert result.includes_column?("col_1")
|
||||
assert_not result.includes_column?("foo")
|
||||
end
|
||||
|
||||
test "length" do
|
||||
assert_equal 3, result.length
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue