1
0
Fork 0
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:
Matthew Draper 2016-02-04 08:02:45 +10:30
parent 7710d7f432
commit cdc112e3ea
12 changed files with 34 additions and 31 deletions

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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)

View file

@ -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

View file

@ -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)

View file

@ -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

View file

@ -22,8 +22,12 @@ module ActiveRecord
end
def arel_attribute(column_name)
if klass
klass.arel_attribute(column_name, arel_table)
else
arel_table[column_name]
end
end
def type(column_name)
if klass

View file

@ -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