ActiveRecord (少なくとも 3.2.1) は空の配列を NULL として扱います。where
呼び出しのプレースホルダはによって処理されsanitize_sql
ます。コードを少したどると、次のようになりますreplace_bind_variables
。
def replace_bind_variables(statement, values) #:nodoc:
raise_if_bind_arity_mismatch(statement, statement.count('?'), values.size)
bound = values.dup
c = connection
statement.gsub('?') { quote_bound_value(bound.shift, c) }
end
そしてquote_bound_value
:
def quote_bound_value(value, c = connection) #:nodoc:
if value.respond_to?(:map) && !value.acts_like?(:string)
if value.respond_to?(:empty?) && value.empty?
c.quote(nil)
else
value.map { |v| c.quote(v) }.join(',')
end
else
c.quote(value)
end
end
空の配列は、4 つの条件すべてを満たし、c.quote(nil)
そこから NULL が取得されます。につながるすべての特別なロジックc.quote(nil)
は、これが意図的な動作であることを示しています。
空のリストで IN (または NOT IN) と言う:
where c in ()
はSQLエラーを生成するはずなので、おそらくARの人々はその悪いSQLを静かにc in (null)
. これらのどちらでもないことに注意してください。
select ... from t where c in (null);
select ... from t where c not in (null);
SQL の NULL の動作により、何らかの結果が生成されるはずです。これは典型的な初心者の間違いであり、AR ユーザーは本当によく知っている必要があります。
私自身は例外を望んでいます.足弾を展開しようとしていることを私に伝えることは、単に別の銃を渡すよりもはるかに友好的です.
エグゼクティブサマリー:
- この「空の配列は NULL を意味する」動作は意図的なものです。
- どちらのステートメントもあまり意味がないため、決して
where('c in (?)', [])
orを試してはいけません。where('c not in (?)', [])
- Ruby コードを更新して、空の配列をチェックし、期待する結果を得るために必要なことをすべて実行します。