mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Rely on the injectable type caster for arel_table
This API will require much less consuming code to change to accomodate the removal of automatic type casting from Arel. As long as the predicates are constructed using the `arel_table` off of an AR subclass, there will be no changes that need to happen.
This commit is contained in:
parent
266ff70001
commit
7eed50c720
6 changed files with 22 additions and 74 deletions
|
@ -235,7 +235,7 @@ module ActiveRecord
|
|||
# scope :published_and_commented, -> { published.and(self.arel_table[:comments_count].gt(0)) }
|
||||
# end
|
||||
def arel_table # :nodoc:
|
||||
@arel_table ||= Arel::Table.new(table_name)
|
||||
@arel_table ||= Arel::Table.new(table_name, type_caster: self)
|
||||
end
|
||||
|
||||
# Returns the Arel engine.
|
||||
|
@ -252,6 +252,12 @@ module ActiveRecord
|
|||
@predicate_builder ||= PredicateBuilder.new(table_metadata)
|
||||
end
|
||||
|
||||
def type_cast_for_database(attribute_name, value)
|
||||
return value if value.is_a?(Arel::Nodes::BindParam)
|
||||
type = type_for_attribute(attribute_name.to_s)
|
||||
type.type_cast_for_database(value)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def relation # :nodoc:
|
||||
|
|
|
@ -8,7 +8,7 @@ module ActiveRecord
|
|||
require 'active_record/relation/predicate_builder/range_handler'
|
||||
require 'active_record/relation/predicate_builder/relation_handler'
|
||||
|
||||
delegate :resolve_column_aliases, :type_cast_for_database, to: :table
|
||||
delegate :resolve_column_aliases, to: :table
|
||||
|
||||
def initialize(table)
|
||||
@table = table
|
||||
|
|
|
@ -19,12 +19,7 @@ module ActiveRecord
|
|||
case values.length
|
||||
when 0 then NullPredicate
|
||||
when 1 then predicate_builder.build(attribute, values.first)
|
||||
else
|
||||
attribute_name = attribute.name
|
||||
casted_values = values.map do |v|
|
||||
predicate_builder.type_cast_for_database(attribute_name, v)
|
||||
end
|
||||
attribute.in(casted_values)
|
||||
else attribute.in(values)
|
||||
end
|
||||
|
||||
unless nils.empty?
|
||||
|
|
|
@ -6,7 +6,6 @@ module ActiveRecord
|
|||
end
|
||||
|
||||
def call(attribute, value)
|
||||
value = predicate_builder.type_cast_for_database(attribute.name, value)
|
||||
attribute.eq(value)
|
||||
end
|
||||
|
||||
|
|
|
@ -6,11 +6,6 @@ module ActiveRecord
|
|||
end
|
||||
|
||||
def call(attribute, value)
|
||||
value = QuotedRange.new(
|
||||
predicate_builder.type_cast_for_database(attribute.name, value.begin),
|
||||
predicate_builder.type_cast_for_database(attribute.name, value.end),
|
||||
value.exclude_end?,
|
||||
)
|
||||
attribute.between(value)
|
||||
end
|
||||
|
||||
|
@ -18,16 +13,5 @@ module ActiveRecord
|
|||
|
||||
attr_reader :predicate_builder
|
||||
end
|
||||
|
||||
class QuotedRange # :nodoc:
|
||||
attr_reader :begin, :end, :exclude_end
|
||||
alias_method :exclude_end?, :exclude_end
|
||||
|
||||
def initialize(begin_val, end_val, exclude)
|
||||
@begin = begin_val
|
||||
@end = end_val
|
||||
@exclude_end = exclude
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -8,12 +8,6 @@ module ActiveRecord
|
|||
@association = association
|
||||
end
|
||||
|
||||
def type_cast_for_database(attribute_name, value)
|
||||
return value if value.is_a?(Arel::Nodes::BindParam) || klass.nil?
|
||||
type = klass.type_for_attribute(attribute_name.to_s)
|
||||
Arel::Nodes::Quoted.new(type.type_cast_for_database(value))
|
||||
end
|
||||
|
||||
def resolve_column_aliases(hash)
|
||||
hash = hash.dup
|
||||
hash.keys.grep(Symbol) do |key|
|
||||
|
@ -35,17 +29,17 @@ module ActiveRecord
|
|||
def associated_table(table_name)
|
||||
return self if table_name == arel_table.name
|
||||
|
||||
arel_table = Arel::Table.new(table_name)
|
||||
association = klass._reflect_on_association(table_name)
|
||||
if association && !association.polymorphic?
|
||||
association_klass = association.klass
|
||||
arel_table = association_klass.arel_table
|
||||
else
|
||||
type_caster = ConnectionAdapterTypeCaster.new(klass.connection, table_name)
|
||||
association_klass = nil
|
||||
arel_table = Arel::Table.new(table_name, type_caster: type_caster)
|
||||
end
|
||||
|
||||
if association
|
||||
TableMetadata.new(association_klass, arel_table, association)
|
||||
else
|
||||
ConnectionAdapterTable.new(klass.connection, arel_table)
|
||||
end
|
||||
TableMetadata.new(association_klass, arel_table, association)
|
||||
end
|
||||
|
||||
def polymorphic_association?
|
||||
|
@ -57,56 +51,26 @@ module ActiveRecord
|
|||
attr_reader :klass, :arel_table, :association
|
||||
end
|
||||
|
||||
# FIXME: We want to get rid of this class. The connection adapter does not
|
||||
# have sufficient knowledge about types, as they could be provided by or
|
||||
# overriden by the ActiveRecord::Base subclass. The case where you reach this
|
||||
# class is if you do a query like:
|
||||
#
|
||||
# Liquid.joins(molecules: :electrons)
|
||||
# .where("molecules.name" => "something", "electrons.name" => "something")
|
||||
#
|
||||
# Since we don't know that we can get to electrons through molecules
|
||||
class ConnectionAdapterTable # :nodoc:
|
||||
def initialize(connection, arel_table)
|
||||
class ConnectionAdapterTypeCaster
|
||||
def initialize(connection, table_name)
|
||||
@connection = connection
|
||||
@arel_table = arel_table
|
||||
@table_name = table_name
|
||||
end
|
||||
|
||||
def type_cast_for_database(attribute_name, value)
|
||||
return value if value.is_a?(Arel::Nodes::BindParam)
|
||||
type = type_for(attribute_name)
|
||||
Arel::Nodes::Quoted.new(type.type_cast_for_database(value))
|
||||
end
|
||||
|
||||
def resolve_column_aliases(hash)
|
||||
hash
|
||||
end
|
||||
|
||||
def arel_attribute(column_name)
|
||||
arel_table[column_name]
|
||||
end
|
||||
|
||||
def associated_with?(*)
|
||||
false
|
||||
end
|
||||
|
||||
def associated_table(table_name)
|
||||
arel_table = Arel::Table.new(table_name)
|
||||
ConnectionAdapterTable.new(klass.connection, arel_table)
|
||||
end
|
||||
|
||||
def polymorphic_association?
|
||||
false
|
||||
type.type_cast_for_database(value)
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
attr_reader :connection, :arel_table
|
||||
attr_reader :connection, :table_name
|
||||
|
||||
private
|
||||
|
||||
def type_for(attribute_name)
|
||||
if connection.schema_cache.table_exists?(arel_table.name)
|
||||
if connection.schema_cache.table_exists?(table_name)
|
||||
column_for(attribute_name).cast_type
|
||||
else
|
||||
Type::Value.new
|
||||
|
@ -114,7 +78,7 @@ module ActiveRecord
|
|||
end
|
||||
|
||||
def column_for(attribute_name)
|
||||
connection.schema_cache.columns_hash(arel_table.name)[attribute_name.to_s]
|
||||
connection.schema_cache.columns_hash(table_name)[attribute_name.to_s]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue