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]
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
# the join table
|
||||
def association_key
|
||||
table[association_key_name]
|
||||
klass.arel_attribute(association_key_name, table)
|
||||
end
|
||||
|
||||
# The name of the key on the model which declares the association
|
||||
|
|
|
@ -256,6 +256,11 @@ module ActiveRecord
|
|||
end
|
||||
end
|
||||
|
||||
def arel_attribute(name, table) # :nodoc:
|
||||
name = attribute_alias(name) if attribute_alias?(name)
|
||||
table[name]
|
||||
end
|
||||
|
||||
def predicate_builder # :nodoc:
|
||||
@predicate_builder ||= PredicateBuilder.new(table_metadata)
|
||||
end
|
||||
|
|
|
@ -192,7 +192,7 @@ module ActiveRecord
|
|||
end
|
||||
|
||||
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_column.in(sti_names)
|
||||
|
|
|
@ -47,7 +47,7 @@ module ActiveRecord
|
|||
|
||||
if !primary_key_value && connection.prefetch_primary_key?(klass.table_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
|
||||
|
||||
|
@ -373,9 +373,9 @@ module ActiveRecord
|
|||
stmt.table(table)
|
||||
|
||||
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
|
||||
stmt.key = table[primary_key]
|
||||
stmt.key = @klass.arel_attribute(primary_key, table)
|
||||
stmt.take(arel.limit)
|
||||
stmt.order(*arel.orders)
|
||||
stmt.wheres = arel.constraints
|
||||
|
@ -527,7 +527,7 @@ module ActiveRecord
|
|||
stmt.from(table)
|
||||
|
||||
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
|
||||
stmt.wheres = arel.constraints
|
||||
end
|
||||
|
|
|
@ -204,15 +204,15 @@ module ActiveRecord
|
|||
yield yielded_relation
|
||||
|
||||
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
|
||||
|
||||
private
|
||||
|
||||
def apply_limits(relation, start, finish)
|
||||
relation = relation.where(table[primary_key].gteq(start)) if start
|
||||
relation = relation.where(table[primary_key].lteq(finish)) if finish
|
||||
relation = relation.where(klass.arel_attribute(primary_key, table).gteq(start)) if start
|
||||
relation = relation.where(klass.arel_attribute(primary_key, table).lteq(finish)) if finish
|
||||
relation
|
||||
end
|
||||
|
||||
|
|
|
@ -155,15 +155,7 @@ module ActiveRecord
|
|||
# See also #ids.
|
||||
#
|
||||
def pluck(*column_names)
|
||||
column_names.map! do |column_name|
|
||||
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?
|
||||
if loaded? && (column_names.map(&:to_s) - @klass.attribute_names - @klass.attribute_aliases.keys).empty?
|
||||
return @records.pluck(*column_names)
|
||||
end
|
||||
|
||||
|
@ -172,7 +164,7 @@ module ActiveRecord
|
|||
else
|
||||
relation = spawn
|
||||
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.cast_values(klass.attribute_types)
|
||||
|
|
|
@ -147,7 +147,7 @@ module ActiveRecord
|
|||
def last(limit = nil)
|
||||
if limit
|
||||
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
|
||||
to_a.last(limit)
|
||||
end
|
||||
|
@ -514,7 +514,7 @@ module ActiveRecord
|
|||
# TODO: once the offset argument is removed from find_nth,
|
||||
# find_nth_with_limit_and_offset can be merged into this method
|
||||
relation = if order_values.empty? && primary_key
|
||||
order(arel_table[primary_key].asc)
|
||||
order(klass.arel_attribute(primary_key, table).asc)
|
||||
else
|
||||
self
|
||||
end
|
||||
|
|
|
@ -3,7 +3,7 @@ module ActiveRecord
|
|||
class RelationHandler # :nodoc:
|
||||
def call(attribute, value)
|
||||
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
|
||||
|
||||
attribute.in(value.arel)
|
||||
|
|
|
@ -1093,8 +1093,8 @@ module ActiveRecord
|
|||
|
||||
def arel_columns(columns)
|
||||
columns.map do |field|
|
||||
if (Symbol === field || String === field) && columns_hash.key?(field.to_s) && !from_clause.value
|
||||
arel_table[field]
|
||||
if (Symbol === field || String === field) && (klass.has_attribute?(field) || klass.attribute_alias?(field)) && !from_clause.value
|
||||
klass.arel_attribute(field, table)
|
||||
elsif Symbol === field
|
||||
connection.quote_table_name(field.to_s)
|
||||
else
|
||||
|
@ -1105,7 +1105,7 @@ module ActiveRecord
|
|||
|
||||
def reverse_sql_order(order_query)
|
||||
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,
|
||||
"Relation has no current order and table has no primary key to be used as default order"
|
||||
end
|
||||
|
@ -1170,12 +1170,10 @@ module ActiveRecord
|
|||
order_args.map! do |arg|
|
||||
case arg
|
||||
when Symbol
|
||||
arg = klass.attribute_alias(arg) if klass.attribute_alias?(arg)
|
||||
table[arg].asc
|
||||
klass.arel_attribute(arg, table).asc
|
||||
when Hash
|
||||
arg.map { |field, dir|
|
||||
field = klass.attribute_alias(field) if klass.attribute_alias?(field)
|
||||
table[field].send(dir.downcase)
|
||||
klass.arel_attribute(field, table).send(dir.downcase)
|
||||
}
|
||||
else
|
||||
arg
|
||||
|
|
|
@ -22,7 +22,11 @@ module ActiveRecord
|
|||
end
|
||||
|
||||
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
|
||||
|
||||
def type(column_name)
|
||||
|
|
|
@ -26,6 +26,10 @@ module ActiveRecord
|
|||
def sanitize_sql_for_order(sql)
|
||||
sql
|
||||
end
|
||||
|
||||
def arel_attribute(name, table)
|
||||
table[name]
|
||||
end
|
||||
end
|
||||
|
||||
def relation
|
||||
|
|
Loading…
Reference in a new issue