提交 5cb261af 编写于 作者: R Ryuta Kamizono

Ensure type cast is not evaluated at relation build time

Some apps would expect that type cast is not evaluated at relation build
time consistently.

Context:

https://github.com/kamipo/rails/commit/b571c4f3f2811b5d3dc8b005707cf8c353abdf03#r31015008
https://github.com/rails/rails/pull/34303

And also this removes extra grouping on IN clause behaved as before.
上级 e47df599
......@@ -22,15 +22,7 @@ def call(attribute, value)
when 1 then predicate_builder.build(attribute, values.first)
else
if nils.empty? && ranges.empty?
type = attribute.type_caster
casted_values = values.map do |raw_value|
type.unchecked_serialize(raw_value) if type.serializable?(raw_value)
end
casted_values.compact!
return Arel::Nodes::HomogeneousIn.new(casted_values, attribute, :in)
return Arel::Nodes::HomogeneousIn.new(values, attribute, :in)
else
attribute.in values.map { |v|
predicate_builder.build_bind_attribute(attribute.name, v)
......
......@@ -40,6 +40,17 @@ def column_name
attribute.name
end
def casted_values
type = attribute.type_caster
casted_values = values.map do |raw_value|
type.unchecked_serialize(raw_value) if type.serializable?(raw_value)
end
casted_values.compact!
casted_values
end
def fetch_attribute(&block)
if attribute
yield attribute
......
......@@ -323,7 +323,6 @@ def visit_Arel_Nodes_Grouping(o, collector)
def visit_Arel_Nodes_HomogeneousIn(o, collector)
collector.preparable = false
collector << "("
collector << quote_table_name(o.table_name) << "." << quote_column_name(o.column_name)
......@@ -333,7 +332,7 @@ def visit_Arel_Nodes_HomogeneousIn(o, collector)
collector << "NOT IN ("
end
values = o.values.map { |v| @connection.quote v }
values = o.casted_values.map { |v| @connection.quote(v) }
expr = if values.empty?
@connection.quote(nil)
......@@ -342,7 +341,7 @@ def visit_Arel_Nodes_HomogeneousIn(o, collector)
end
collector << expr
collector << "))"
collector << ")"
collector
end
......
......@@ -25,6 +25,20 @@ def test_type_casting_nested_joins
assert_equal [comment], Comment.joins(post: :author).where(authors: { id: "2-foo" })
end
def test_type_cast_is_not_evaluated_at_relation_build_time
posts = nil
assert_not_called_on_instance_of(Type::Value, :cast) do
posts = Post.where(id: "1-foo")
end
assert_equal [posts(:welcome)], posts.to_a
assert_not_called_on_instance_of(Type::Value, :cast) do
posts = Post.where(id: ["1-foo", "bar"])
end
assert_equal [posts(:welcome)], posts.to_a
end
def test_where_copies_bind_params
author = authors(:david)
posts = author.posts.where("posts.id != 1")
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册