LoginSignup
5
2

More than 5 years have passed since last update.

ActiveRecordでSQLite3のBoolean値は0/1ではなく'f'/'t'

Last updated at Posted at 2016-10-05

ActiveRecord + SQLite3のBoolean値でハマった。

Boolean値としてtrueが入っている(ように見える)レコードがあるとき、
そのBoolean値を検索条件にするとヒットしないことがある。

Widget.find(1)
# => { id: 1, name: "hoge", valid: true }

Widget.where(valid: true).first
# => nil # あれ?

DBの中身をコマンドラインで直接見てみる。


sqlite> SELECT * FROM widgets;
id  name  valid
--- ----- ------
1   hoge  1

うーん、SQLite3ってBoolean値を直接サポートしてないからその辺か?
SQLite3側のドキュメントを見ると、以下のように書いてあるから良さそうだけど。

SQLite does not have a separate Boolean storage class. Instead,
Boolean values are stored as integers 0 (false) and 1 (true).
https://www.sqlite.org/datatype3.html

ActiveRecord側を調べてみる。
こんな記事があった。
http://stackoverflow.com/questions/23223821/sqlite-boolean-t-and-f-with-rails-active-record
http://stackoverflow.com/questions/6013121/rails-3-sqlite3-boolean-false

Boolean値は0/1ではなく'f'/'t'らしい。
コマンドラインで変更してみる。

sqlite> UPDATE widgets SET valid = 't';
sqlite> SELECT * FROM widgets;
id  name  valid
--- ----- ------
1   hoge  t

これでいけるか?

Widget.where(valid: true).first
# => { id: 1, name: "hoge", valid: true }

できた。

※補足
データ生成・編集もすべてActiveRecordでやっていれば問題は発生しない(と思う)。
外部(例えばsqlite3のコマンドライン)で作ったデータを使うときには注意が必要なようだ。

追記

Rails 5.2から仕様が変わったとコメントで教えて頂きました。
詳しくはこちの記事を参照してください。
Rails 5.2 で SQLite3 の boolean の値が変わった

5
2
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2