2011-05-16 45 views
9

我試圖在SQLite3表中插入一個假的布爾值,但它總是插入一個真正的值。Rails 3 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 

當我嘗試用Rails它產生以下SQL插入:所以它插入真到我的數據庫

INSERT INTO "users" ("name", "active") VALUES ('test', 'f') 

SQLite的對待 'F' 爲真。我希望它生成的查詢是:

INSERT INTO "users" ("name", "active") VALUES ('test', false) 

我在做什麼錯?

導軌:3.0.7

sqlite3的寶石:1.3.3

+0

什麼是產生與「F」的SQL你的Rails代碼? – 2011-05-16 04:21:49

+0

生成的HTML看起來像這樣:


Mike 2011-05-16 04:42:36

+0

控制器是一個簡單的REST創建。 – Mike 2011-05-16 04:44:55

回答

21

SQLite的使用1 for true and 0 for false

SQLite沒有一個單獨的布爾存儲類。相反,布爾值被存儲爲整數0(假)和1(真)。

但SQLite的也有一個鬆散型的系統和自動轉換東西,所以你'f'可能是被解釋爲「真」一感實性只是因爲它不爲零。

有點挖掘表明你已經在Rails 3.0.7 SQLiteAdapter中發現了一個bug。在active_record/connection_adapters/abstract/quoting.rb,我們發現這些:

def quoted_true 
    "'t'" 
end 

def quoted_false 
    "'f'" 
end 

所以,在默認情況下,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 

但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。

+0

是的,我知道這一點。我只是不知道爲什麼它使用'f'而不是false或0,因爲0在POST中傳遞。 – Mike 2011-05-16 04:46:17

+0

@Mike:請看看我的更新。我刪除了原來的答案,然後復活了它,並根據ActiveRecord數據庫適配器源代碼的快速回顧對其進行了更新。 – 2011-05-16 05:43:20

+0

這就是我的想法......我不能成爲第一個遇到這個錯誤的人,這讓我覺得這與我的環境有關。我會稍等一下,看看其他人是否有其他解釋,否則我會給你信用。 – Mike 2011-05-16 21:16:49

4

我碰到這個跑爲好,這裏是如何猴補丁:我

require 'active_record/connection_adapters/sqlite_adapter' 
module ActiveRecord 
    module ConnectionAdapters 
    class SQLite3Adapter < SQLiteAdapter 
     def quoted_true; '1' end 
     def quoted_false; '0' end 
    end 
    end 
end 

不了怎麼我還是碰到這個錯誤運行?

+0

使用't'和'f'而不是'1'和'0'。這應該是一個評論,而不是一個答案。 – 2014-12-23 02:58:34

+0

這對Rails 5不適用。你有更新的版本嗎? – thisismydesign 2018-01-31 23:39:30

3

您可能會發現有用下面的代碼片段添加與實際工作on Rails的4 SQLite的布爾列兼容性(也張貼在https://gist.github.com/ajoman/9391708):

# config/initializers/sqlite3_adapter_patch.rb 

module ActiveRecord 
    module ConnectionAdapters 
    class SQLite3Adapter < AbstractAdapter 
     QUOTED_TRUE, QUOTED_FALSE = "'t'", "'f'" 

     def quoted_true 
     QUOTED_TRUE 
     end 

     def quoted_false 
     QUOTED_FALSE 
     end 
    end 
    end 
end 
+0

這對Rails 5不適用。你有更新的版本嗎? – thisismydesign 2018-01-31 23:39:25

+0

@thisismydesign抱歉,我沒有更新的版本,因爲我沒有使用SQLite進行Rails開發。 – 2018-02-02 08:15:12

0

這個版本的作品中的Rails 4.1。

require 'active_record/connection_adapters/sqlite_adapter' 

module ActiveRecord::ConnectionAdapters::SQLite3Adapter 
    QUOTED_TRUE, QUOTED_FALSE = 't'.freeze, 'f'.freeze 

    def quoted_true; QUOTED_TRUE end 
    def quoted_false; QUOTED_FALSE end 
end 

的常量和.freeze是性能,所以紅寶石不必重新生成這些字符串和垃圾收集他們對每一個電話。