2013-10-01 26 views
1

我有一個奇怪的問題,我只是無法弄清楚。Rails 4與MySQL的備用主鍵

我想使用mysql的羣集能力來在磁盤上彼此相鄰存儲相關記錄。 Mysql通過表上的主鍵進行集羣,這對於默認的導軌模型來說是ID。

但是,對於很多表格來說,表格的主鍵可能是有意義的,例如,user_id,subscription_id,在每個表格旁邊聚集相關記錄,並且當您詢問時進行非常有效的查找用戶所有訂閱的數據庫。

要做到這一點,我創建了一個MySQL表所示:

execute('create table subscriptions (
      id   integer not null auto_increment, 
      user_id integer not null, 
      feed_id integer not null, 
      folder_id integer, 
      created_at  datetime, 
      updated_at  datetime, 
      primary key (user_id, feed_id), 
      key id (id) 
     ) engine=InnoDB default charset=utf8'); 

請注意,我的PK是USER_ID,FEED_ID但我仍然有本ID列,我想軌仍然使用它作爲是什麼相信是桌上的PK。

首先,這一點都沒有,直到我設置工作:

class Subscription < ActiveRecord::Base 

    self.primary_key = 'id' 
    ... 
end 

現在到了陌生的一部分。

當我運行測試中,我得到一個奇怪的錯誤:

Mysql::Error: Field 'id' doesn't have a default value: INSERT INTO `subscriptions` 

但是 - 如果我堅持在開發模式的應用程序,並通過網頁做的操作,它工作得很好。

很多谷歌搜索後,我發現猴子補丁停止Rails的設置MySQL成爲更嚴格的模式:

class ActiveRecord::ConnectionAdapters::MysqlAdapter 

private 
    alias_method :configure_connection_without_strict_mode, :configure_connection 

    def configure_connection 
    configure_connection_without_strict_mode 
    strict_mode = "SQL_MODE=''" 
    execute("SET #{strict_mode}", :skip_logging) 
    end 
end 

如果我補充這一點,我的測試套裝似乎工作(對於大多數測試,但不全部),但是創建的任何模型的ID均爲零。

再次在生產模式下,通過網頁工作得很好,模型得到一個auto_increment ID預期。

有沒有人有任何想法,我可以做什麼這使我的測試套件在此設置中正常工作?

+0

不會使用UUID主鍵比這更可靠嗎? – tadman

+0

不確定UUID PK。它實際上只是另一個與ID序列相似的代理PK。我並不想開始討論MySQL集羣,但通過在user_id,feed_id上使用PK,這意味着即使用戶長時間創建Feed時,它們也將全部存儲在磁盤上,允許所有這些數據以一個數據庫讀取或兩個而不是多個讀取。它也是桌子上的天然鑰匙,因爲桌子在這雙桌子上應該是獨一無二的。 –

+0

爲什麼不在'(user_id,feed_id)'對上拋出一個唯一的約束/索引並且讓​​PK單獨存在?對於Rails來說,這可能比試圖混淆PK更容易。 –

回答

0

我想清楚發生了什麼事。

我不記得的是開發數據庫是通過對數據庫運行遷移創建的,該數據庫也生成schema.rb文件。然後使用schema.rb文件加載測試數據庫。

因此,雖然我的開發數據庫看起來和我的預期一樣,但測試數據庫看起來不同 - 看起來生成schema.rb文件的代碼無法理解我創建的數據庫格式,也沒有創建反映的schema.rb我的遷移正確。

如果我打開我的測試數據庫:

$ rake db:migrate RAILS_ENV=test 

然後運行我的測試套件:

$ rake test:all 

事情正常工作。這是因爲測試:在運行測試套件之前,所有任務都不會重新加載數據庫。

所以,我在問題中描述了創建一個替代主鍵,同時保持導軌ID鍵工作,除了schema.rb部分。