提交 cdc112e3 编写于 作者: M Matthew Draper

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.
上级 7710d7f4
......@@ -75,7 +75,7 @@ def join_constraints(foreign_table, foreign_klass, node, join_type, tables, scop
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 @@ def association_key_name
# 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 @@ def arel_engine # :nodoc:
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 @@ def find_sti_class(type_name)
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 @@ def insert(values) # :nodoc:
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 @@ def update_all(updates)
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 @@ def delete_all(conditions = nil)
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 @@ def in_batches(of: 1000, start: nil, finish: nil, load: false)
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 @@ def calculate(operation, column_name)
# 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 @@ def pluck(*column_names)
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 @@ def first!
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 @@ def find_nth_with_limit(index, limit)
# 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 @@ class PredicateBuilder
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 @@ def build_select(arel)
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 @@ def arel_columns(columns)
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 @@ def preprocess_order_args(order_args)
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 @@ def resolve_column_aliases(hash)
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 @@ def sanitize_sql(sql)
def sanitize_sql_for_order(sql)
sql
end
def arel_attribute(name, table)
table[name]
end
end
def relation
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册