Rails 3 SQLite3 Boolean false

Mik*_*ike 9 sqlite ruby-on-rails ruby-on-rails-3 rails-activerecord

我试图在SQLite3表中插入一个错误的布尔值,但它总是插入一个真值.

这是我的迁移:

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
Run Code Online (Sandbox Code Playgroud)

当我尝试使用rails插入时,它会生成以下SQL:

INSERT INTO "users" ("name", "active") VALUES ('test', 'f')
Run Code Online (Sandbox Code Playgroud)

SQLite将'f'视为true,因此它将true插入到我的数据库中.我想要它生成的查询是:

INSERT INTO "users" ("name", "active") VALUES ('test', false)
Run Code Online (Sandbox Code Playgroud)

我究竟做错了什么?

rails:3.0.7

sqlite3 gem:1.3.3

mu *_*ort 21

SQLite使用1表示true,0表示false表示:

SQLite没有单独的布尔存储类.相反,布尔值存储为整数0(假)和1(真).

但SQLite也有一个松散的类型系统并自动转换东西,因此你'f'可能被解释为具有"真实"的真实性,因为它不是零.

一点挖掘表明您在Rails 3.0.7 SQLiteAdapter中发现了一个错误.在active_record/connection_adapters/abstract/quoting.rb,我们发现这些:

def quoted_true
  "'t'"
end

def quoted_false
  "'f'"
end
Run Code Online (Sandbox Code Playgroud)

因此,默认情况下,ActiveRecord假定数据库理解't'并且'f'对于布尔列.MySQL适配器会覆盖它们以使用其tinyint布尔列的实现:

QUOTED_TRUE, QUOTED_FALSE = '1'.freeze, '0'.freeze

#...

def quoted_true
  QUOTED_TRUE
end

def quoted_false
  QUOTED_FALSE
end
Run Code Online (Sandbox Code Playgroud)

但SQLite的适配器不提供自己的实现quoted_truequoted_false因此它的不使用SQLite的布尔工作的默认值.

't''f'PostgreSQL中布尔工作,所以也许每个人都使用PostgreSQL了Rails 3或者他们只是没有注意到,他们的查询工作不正常.

我对此感到有些惊讶,希望有人可以指出我出错的地方,你不能成为第一个在SQLite中使用Rails 3的布尔列的人.

尝试猴子修补def quoted_true;'1';enddef quoted_false;'0';end进入ActiveRecord::ConnectionAdapters::SQLiteAdapter(或暂时手动编辑它们active_record/connection_adapters/sqlite_adapter.rb),看看你是否得到合理的SQL.

  • 事实证明sqlite适配器没有任何问题.这是我的数据库查看软件,其中有错误.非常感谢你的深度回答,我希望我能给你信任. (2认同)
  • @Mike:Rails在SQLite数据库中使用`'t'`和`'f'`作为布尔值,对吧?只要只有Rails使用数据库,SQL32就会将内容视为字符串,因此DDL中的列类型主要是建议性的.我只是好奇我是否正确阅读了源代码,也许我会设置自己的Rails/SQLite测试应用程序并查看. (2认同)