mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Defer Arel attribute lookup to the model class
This still isn't as separated as I'd like, but it at least moves most of the burden of alias mapping in one place.
This commit is contained in:
parent
7710d7f432
commit
cdc112e3ea
12 changed files with 34 additions and 31 deletions
|
@ -75,7 +75,7 @@ module ActiveRecord
|
||||||
column = klass.columns_hash[reflection.type.to_s]
|
column = klass.columns_hash[reflection.type.to_s]
|
||||||
|
|
||||||
binds << Relation::QueryAttribute.new(column.name, value, klass.type_for_attribute(column.name))
|
binds << Relation::QueryAttribute.new(column.name, value, klass.type_for_attribute(column.name))
|
||||||
constraint = constraint.and table[reflection.type].eq(Arel::Nodes::BindParam.new)
|
constraint = constraint.and klass.arel_attribute(reflection.type, table).eq(Arel::Nodes::BindParam.new)
|
||||||
end
|
end
|
||||||
|
|
||||||
joins << table.create_join(table, table.create_on(constraint), join_type)
|
joins << table.create_join(table, table.create_on(constraint), join_type)
|
||||||
|
|
|
@ -47,7 +47,7 @@ module ActiveRecord
|
||||||
# This is overridden by HABTM as the condition should be on the foreign_key column in
|
# This is overridden by HABTM as the condition should be on the foreign_key column in
|
||||||
# the join table
|
# the join table
|
||||||
def association_key
|
def association_key
|
||||||
table[association_key_name]
|
klass.arel_attribute(association_key_name, table)
|
||||||
end
|
end
|
||||||
|
|
||||||
# The name of the key on the model which declares the association
|
# The name of the key on the model which declares the association
|
||||||
|
|
|
@ -256,6 +256,11 @@ module ActiveRecord
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def arel_attribute(name, table) # :nodoc:
|
||||||
|
name = attribute_alias(name) if attribute_alias?(name)
|
||||||
|
table[name]
|
||||||
|
end
|
||||||
|
|
||||||
def predicate_builder # :nodoc:
|
def predicate_builder # :nodoc:
|
||||||
@predicate_builder ||= PredicateBuilder.new(table_metadata)
|
@predicate_builder ||= PredicateBuilder.new(table_metadata)
|
||||||
end
|
end
|
||||||
|
|
|
@ -192,7 +192,7 @@ module ActiveRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
def type_condition(table = arel_table)
|
def type_condition(table = arel_table)
|
||||||
sti_column = table[inheritance_column]
|
sti_column = arel_attribute(inheritance_column, table)
|
||||||
sti_names = ([self] + descendants).map(&:sti_name)
|
sti_names = ([self] + descendants).map(&:sti_name)
|
||||||
|
|
||||||
sti_column.in(sti_names)
|
sti_column.in(sti_names)
|
||||||
|
|
|
@ -47,7 +47,7 @@ module ActiveRecord
|
||||||
|
|
||||||
if !primary_key_value && connection.prefetch_primary_key?(klass.table_name)
|
if !primary_key_value && connection.prefetch_primary_key?(klass.table_name)
|
||||||
primary_key_value = connection.next_sequence_value(klass.sequence_name)
|
primary_key_value = connection.next_sequence_value(klass.sequence_name)
|
||||||
values[klass.arel_table[klass.primary_key]] = primary_key_value
|
values[klass.arel_attribute(klass.primary_key, table)] = primary_key_value
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -373,9 +373,9 @@ module ActiveRecord
|
||||||
stmt.table(table)
|
stmt.table(table)
|
||||||
|
|
||||||
if joins_values.any?
|
if joins_values.any?
|
||||||
@klass.connection.join_to_update(stmt, arel, table[primary_key])
|
@klass.connection.join_to_update(stmt, arel, @klass.arel_attribute(primary_key, table))
|
||||||
else
|
else
|
||||||
stmt.key = table[primary_key]
|
stmt.key = @klass.arel_attribute(primary_key, table)
|
||||||
stmt.take(arel.limit)
|
stmt.take(arel.limit)
|
||||||
stmt.order(*arel.orders)
|
stmt.order(*arel.orders)
|
||||||
stmt.wheres = arel.constraints
|
stmt.wheres = arel.constraints
|
||||||
|
@ -527,7 +527,7 @@ module ActiveRecord
|
||||||
stmt.from(table)
|
stmt.from(table)
|
||||||
|
|
||||||
if joins_values.any?
|
if joins_values.any?
|
||||||
@klass.connection.join_to_delete(stmt, arel, table[primary_key])
|
@klass.connection.join_to_delete(stmt, arel, @klass.arel_attribute(primary_key, table))
|
||||||
else
|
else
|
||||||
stmt.wheres = arel.constraints
|
stmt.wheres = arel.constraints
|
||||||
end
|
end
|
||||||
|
|
|
@ -204,15 +204,15 @@ module ActiveRecord
|
||||||
yield yielded_relation
|
yield yielded_relation
|
||||||
|
|
||||||
break if ids.length < of
|
break if ids.length < of
|
||||||
batch_relation = relation.where(table[primary_key].gt(primary_key_offset))
|
batch_relation = relation.where(klass.arel_attribute(primary_key, table).gt(primary_key_offset))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def apply_limits(relation, start, finish)
|
def apply_limits(relation, start, finish)
|
||||||
relation = relation.where(table[primary_key].gteq(start)) if start
|
relation = relation.where(klass.arel_attribute(primary_key, table).gteq(start)) if start
|
||||||
relation = relation.where(table[primary_key].lteq(finish)) if finish
|
relation = relation.where(klass.arel_attribute(primary_key, table).lteq(finish)) if finish
|
||||||
relation
|
relation
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -155,15 +155,7 @@ module ActiveRecord
|
||||||
# See also #ids.
|
# See also #ids.
|
||||||
#
|
#
|
||||||
def pluck(*column_names)
|
def pluck(*column_names)
|
||||||
column_names.map! do |column_name|
|
if loaded? && (column_names.map(&:to_s) - @klass.attribute_names - @klass.attribute_aliases.keys).empty?
|
||||||
if column_name.is_a?(Symbol) && attribute_alias?(column_name)
|
|
||||||
attribute_alias(column_name)
|
|
||||||
else
|
|
||||||
column_name.to_s
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if loaded? && (column_names - @klass.column_names).empty?
|
|
||||||
return @records.pluck(*column_names)
|
return @records.pluck(*column_names)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -172,7 +164,7 @@ module ActiveRecord
|
||||||
else
|
else
|
||||||
relation = spawn
|
relation = spawn
|
||||||
relation.select_values = column_names.map { |cn|
|
relation.select_values = column_names.map { |cn|
|
||||||
columns_hash.key?(cn) ? arel_table[cn] : cn
|
@klass.has_attribute?(cn) || @klass.attribute_alias?(cn) ? klass.arel_attribute(cn, table) : cn
|
||||||
}
|
}
|
||||||
result = klass.connection.select_all(relation.arel, nil, bound_attributes)
|
result = klass.connection.select_all(relation.arel, nil, bound_attributes)
|
||||||
result.cast_values(klass.attribute_types)
|
result.cast_values(klass.attribute_types)
|
||||||
|
|
|
@ -147,7 +147,7 @@ module ActiveRecord
|
||||||
def last(limit = nil)
|
def last(limit = nil)
|
||||||
if limit
|
if limit
|
||||||
if order_values.empty? && primary_key
|
if order_values.empty? && primary_key
|
||||||
order(arel_table[primary_key].desc).limit(limit).reverse
|
order(klass.arel_attribute(primary_key, table).desc).limit(limit).reverse
|
||||||
else
|
else
|
||||||
to_a.last(limit)
|
to_a.last(limit)
|
||||||
end
|
end
|
||||||
|
@ -514,7 +514,7 @@ module ActiveRecord
|
||||||
# TODO: once the offset argument is removed from find_nth,
|
# TODO: once the offset argument is removed from find_nth,
|
||||||
# find_nth_with_limit_and_offset can be merged into this method
|
# find_nth_with_limit_and_offset can be merged into this method
|
||||||
relation = if order_values.empty? && primary_key
|
relation = if order_values.empty? && primary_key
|
||||||
order(arel_table[primary_key].asc)
|
order(klass.arel_attribute(primary_key, table).asc)
|
||||||
else
|
else
|
||||||
self
|
self
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,7 +3,7 @@ module ActiveRecord
|
||||||
class RelationHandler # :nodoc:
|
class RelationHandler # :nodoc:
|
||||||
def call(attribute, value)
|
def call(attribute, value)
|
||||||
if value.select_values.empty?
|
if value.select_values.empty?
|
||||||
value = value.select(value.klass.arel_table[value.klass.primary_key])
|
value = value.select(value.klass.arel_attribute(value.klass.primary_key, value.klass.arel_table))
|
||||||
end
|
end
|
||||||
|
|
||||||
attribute.in(value.arel)
|
attribute.in(value.arel)
|
||||||
|
|
|
@ -1093,8 +1093,8 @@ module ActiveRecord
|
||||||
|
|
||||||
def arel_columns(columns)
|
def arel_columns(columns)
|
||||||
columns.map do |field|
|
columns.map do |field|
|
||||||
if (Symbol === field || String === field) && columns_hash.key?(field.to_s) && !from_clause.value
|
if (Symbol === field || String === field) && (klass.has_attribute?(field) || klass.attribute_alias?(field)) && !from_clause.value
|
||||||
arel_table[field]
|
klass.arel_attribute(field, table)
|
||||||
elsif Symbol === field
|
elsif Symbol === field
|
||||||
connection.quote_table_name(field.to_s)
|
connection.quote_table_name(field.to_s)
|
||||||
else
|
else
|
||||||
|
@ -1105,7 +1105,7 @@ module ActiveRecord
|
||||||
|
|
||||||
def reverse_sql_order(order_query)
|
def reverse_sql_order(order_query)
|
||||||
if order_query.empty?
|
if order_query.empty?
|
||||||
return [table[primary_key].desc] if primary_key
|
return [klass.arel_attribute(primary_key, table).desc] if primary_key
|
||||||
raise IrreversibleOrderError,
|
raise IrreversibleOrderError,
|
||||||
"Relation has no current order and table has no primary key to be used as default order"
|
"Relation has no current order and table has no primary key to be used as default order"
|
||||||
end
|
end
|
||||||
|
@ -1170,12 +1170,10 @@ module ActiveRecord
|
||||||
order_args.map! do |arg|
|
order_args.map! do |arg|
|
||||||
case arg
|
case arg
|
||||||
when Symbol
|
when Symbol
|
||||||
arg = klass.attribute_alias(arg) if klass.attribute_alias?(arg)
|
klass.arel_attribute(arg, table).asc
|
||||||
table[arg].asc
|
|
||||||
when Hash
|
when Hash
|
||||||
arg.map { |field, dir|
|
arg.map { |field, dir|
|
||||||
field = klass.attribute_alias(field) if klass.attribute_alias?(field)
|
klass.arel_attribute(field, table).send(dir.downcase)
|
||||||
table[field].send(dir.downcase)
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
arg
|
arg
|
||||||
|
|
|
@ -22,7 +22,11 @@ module ActiveRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
def arel_attribute(column_name)
|
def arel_attribute(column_name)
|
||||||
arel_table[column_name]
|
if klass
|
||||||
|
klass.arel_attribute(column_name, arel_table)
|
||||||
|
else
|
||||||
|
arel_table[column_name]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def type(column_name)
|
def type(column_name)
|
||||||
|
|
|
@ -26,6 +26,10 @@ module ActiveRecord
|
||||||
def sanitize_sql_for_order(sql)
|
def sanitize_sql_for_order(sql)
|
||||||
sql
|
sql
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def arel_attribute(name, table)
|
||||||
|
table[name]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def relation
|
def relation
|
||||||
|
|
Loading…
Reference in a new issue