提交 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 ...@@ -75,7 +75,7 @@ def join_constraints(foreign_table, foreign_klass, node, join_type, tables, scop
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 @@ def association_key_name ...@@ -47,7 +47,7 @@ def association_key_name
# 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 @@ def arel_engine # :nodoc: ...@@ -256,6 +256,11 @@ def arel_engine # :nodoc:
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 @@ def find_sti_class(type_name) ...@@ -192,7 +192,7 @@ def find_sti_class(type_name)
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 @@ def insert(values) # :nodoc: ...@@ -47,7 +47,7 @@ def insert(values) # :nodoc:
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 @@ def update_all(updates) ...@@ -373,9 +373,9 @@ def update_all(updates)
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 @@ def delete_all(conditions = nil) ...@@ -527,7 +527,7 @@ def delete_all(conditions = nil)
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 @@ def in_batches(of: 1000, start: nil, finish: nil, load: false) ...@@ -204,15 +204,15 @@ def in_batches(of: 1000, start: nil, finish: nil, load: false)
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 @@ def calculate(operation, column_name) ...@@ -155,15 +155,7 @@ def calculate(operation, column_name)
# 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 @@ def pluck(*column_names) ...@@ -172,7 +164,7 @@ def pluck(*column_names)
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 @@ def first! ...@@ -147,7 +147,7 @@ def first!
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 @@ def find_nth_with_limit(index, limit) ...@@ -514,7 +514,7 @@ def find_nth_with_limit(index, limit)
# 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 @@ class PredicateBuilder ...@@ -3,7 +3,7 @@ class PredicateBuilder
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 @@ def build_select(arel) ...@@ -1093,8 +1093,8 @@ def build_select(arel)
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 @@ def arel_columns(columns) ...@@ -1105,7 +1105,7 @@ def arel_columns(columns)
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 @@ def preprocess_order_args(order_args) ...@@ -1170,12 +1170,10 @@ def preprocess_order_args(order_args)
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 @@ def resolve_column_aliases(hash) ...@@ -22,7 +22,11 @@ def resolve_column_aliases(hash)
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 @@ def sanitize_sql(sql) ...@@ -26,6 +26,10 @@ def sanitize_sql(sql)
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
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册