提交 a11a8ff7 编写于 作者: S Sean Griffin

Fall back to type casting from the connection adapter

There are several valid cases where right now we can't determine the
association's class in a call to `where`. In these cases, we can fall
back to casting by looking up the column from the connection adapter
(which is what happens right now when we fall through to Arel)

This is ugly, and since we're trying to separate the concept of a type
from a column, I'd like to remove it in the future. The problem
basically comes down to this:

    Liquid.joins(molecules: :electrons)
      .where("molecules.name" => "something", "electrons.name" => "something")

The hash in this case will turn into:

    {
      molecules: { name: "something" },
      electrons: { name: "something" },
    }

What we actually need is:

    {
      molecules: {
        name: "something",
        electrons: { name: "something" },
      }
    }

/cc @mrgilman
上级 5f521cbf
......@@ -33,12 +33,19 @@ def associated_with?(association_name)
end
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?
klass = association.klass
association_klass = association.klass
end
if association
TableMetadata.new(association_klass, arel_table, association)
else
ConnectionAdapterTable.new(klass.connection, arel_table)
end
TableMetadata.new(klass, arel_table, association)
end
def polymorphic_association?
......@@ -49,4 +56,65 @@ def polymorphic_association?
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)
@connection = connection
@arel_table = arel_table
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
end
protected
attr_reader :connection, :arel_table
private
def type_for(attribute_name)
if connection.schema_cache.table_exists?(arel_table.name)
column_for(attribute_name).cast_type
else
Type::Value.new
end
end
def column_for(attribute_name)
connection.schema_cache.columns_hash(arel_table.name)[attribute_name.to_s]
end
end
end
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册