问题描述
我试图在 SQLite3 表中插入一个假布尔值,但它总是插入一个真值.
I'm trying to insert a false boolean value in a SQLite3 table but it always inserts a true value.
这是我的迁移:
class CreateUsers < ActiveRecord::Migration
def self.up
create_table :users do |t|
t.column :name, :string
t.column :active, :boolean, :default => false, :null => false
end
end
def self.down
drop_table :resources
end
end
当我尝试使用 rails 插入时,它会生成以下 SQL:
When I try to insert using rails it produces the following SQL:
INSERT INTO "users" ("name", "active") VALUES ('test', 'f')
SQLite 将 'f' 视为 true,因此它会将 true 插入到我的数据库中.我希望它生成的查询是:
SQLite treats 'f' as true so it inserts true into my database. The query I want it to generate is:
INSERT INTO "users" ("name", "active") VALUES ('test', false)
我做错了什么?
导轨:3.0.7
sqlite3 gem: 1.3.3
sqlite3 gem: 1.3.3
推荐答案
SQLite 使用 1 表示 true 和0 表示假:
SQLite uses 1 for true and 0 for false:
SQLite 没有单独的布尔存储类.相反,布尔值存储为整数 0(假)和 1(真).
但 SQLite 也有一个松散的类型系统并自动转换,所以你的 'f'
可能被解释为具有true"的真实性,因为它不是零.
But SQLite also has a loose type system and automatically casts things so your 'f'
is probably being interpreted as having a truthiness of "true" simply because it isn't zero.
一点点挖掘表明您在 Rails 3.0.7 SQLiteAdapter 中发现了一个错误.在 active_record/connection_adapters/abstract/quoting.rb
中,我们找到了这些:
A bit of digging indicates that you have found a bug in the Rails 3.0.7 SQLiteAdapter. In active_record/connection_adapters/abstract/quoting.rb
, we find these:
def quoted_true
"'t'"
end
def quoted_false
"'f'"
end
因此,默认情况下,ActiveRecord 假定数据库理解布尔列的 't'
和 'f'
.MySQL 适配器覆盖这些以与布尔列的 tinyint
实现一起工作:
So, by default, ActiveRecord assumes that the database understands 't'
and 'f'
for boolean columns. The MySQL adaptor overrides these to work with its tinyint
implementation of boolean columns:
QUOTED_TRUE, QUOTED_FALSE = '1'.freeze, '0'.freeze
#...
def quoted_true
QUOTED_TRUE
end
def quoted_false
QUOTED_FALSE
end
但是 SQLite 适配器不提供自己的 quoted_true
或 quoted_false
实现,因此它获得了不适用于 SQLite 布尔值的默认值.
But the SQLite adapter does not provide its own implementations of quoted_true
or quoted_false
so it gets the defaults which don't work with SQLite's booleans.
't'
和 'f'
布尔值在 PostgreSQL 中工作,所以也许每个人都在使用 PostgreSQL 和 Rails 3,或者他们只是没有注意到他们的查询是't 工作正常.
The 't'
and 'f'
booleans work in PostgreSQL so maybe everyone is using PostgreSQL with Rails 3 or they're just not noticing that their queries aren't working properly.
我对此感到有点惊讶,希望有人能指出我哪里出错了,您不可能是第一个在 SQLite 中使用带有 Rails 3 的布尔列的人.
I'm a little surprised by this and hopefully someone can point out where I've gone wrong, you can't be the first person to use a boolean column in SQLite with Rails 3.
尝试将 defquoted_true;'1';end
和 defquoted_false;'0';end
修补到 ActiveRecord::ConnectionAdapters::SQLiteAdapter
(或临时手工编辑它们到 active_record/connection_adapters/sqlite_adapter.rb
),看看你是否得到了合理的 SQL.
Try monkey patching def quoted_true;'1';end
and def quoted_false;'0';end
into ActiveRecord::ConnectionAdapters::SQLiteAdapter
(or temporarily hand-edit them into active_record/connection_adapters/sqlite_adapter.rb
) and see if you get sensible SQL.
这篇关于Rails 3 SQLite3 布尔假的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!