📌
ActiveRecord で where するときにカラムの型と異なる値を渡すと NULL になる
NOTE: この記事では Rails 7.1.4
+ sqlite3
で動作検証しています。
例えば次のような schema のテーブルに対して
ActiveRecord::Schema.define do
create_table :users, force: true do |t|
t.integer :count
t.boolean :active
t.timestamps
end
end
次のように .where
で count
に数値以外を渡すとエラーにならずに NULL
として扱われます。
pp ActiveRecord::VERSION::STRING
# => "7.1.4"
class User < ActiveRecord::Base
end
puts User.where(count: "hoge").to_sql
# => SELECT "users".* FROM "users" WHERE "users"."count" = NULL
これは内部で "hoge"
を integer 型
にキャストするときにキャストできず NULL
の値として変換されるからになります。
逆に integer 型
にキャストできる場合は文字列の場合でも数値として変換されます。
# "42" は文字列だが 42 としてキャストされる
puts User.where(count: "42").to_sql
# =>< SELECT "users".* FROM "users" WHERE "users"."count" = 42
他にも boolean 型
の場合はそれっぽい値を 0 / 1
として変換します。
puts User.where(active: "true").to_sql
# => SELECT "users".* FROM "users" WHERE "users"."active" = 1
puts User.where(active: "false").to_sql
# => SELECT "users".* FROM "users" WHERE "users"."active" = 0
puts User.where(active: "42").to_sql
# => SELECT "users".* FROM "users" WHERE "users"."active" = 1
puts User.where(active: "hoge").to_sql
# => SELECT "users".* FROM "users" WHERE "users"."active" = 1
puts User.where(active: "0").to_sql
# => SELECT "users".* FROM "users" WHERE "users"."active" = 0
puts User.where(active: "").to_sql
# => SELECT "users".* FROM "users" WHERE "users"."active" = NULL
ただ、このあたりの型キャストのされ方はもしかしたら使用する RDBMS によって挙動が変わるかもしれません。
Discussion