2013-09-05 23 views
2

我正在通過Michael Hartel的6.3教程,並且需要user_spec模型的替代代碼。他擁有的代碼是:ROR的find_by替代方案

let(:found_user) { User.find_by(email: @user.email) } 

看起來我可以在哪裏使用,但不確定正確的語法。我嘗試了以下幾種變體:

let(:found_user) { User.where(:email => "@user.email")} 

我敢肯定這是一個相當簡單的答案,但不能完全得到它。

+0

歡迎計算器:-) – fotanus

+0

fotanus,感謝這麼多的編輯和歡迎。我找不到突出顯示代碼的選項,但下次我再仔細檢查。我必須在頭燈上還有一隻「鹿」。再次感謝。 – user2751598

回答

3
let(:found_user){User.where(email: @user.email).first} 

let(:found_user){User.find_by_email(@user.email)} 

即使用where第一個返回匹配where子句用戶的集合,這就是爲什麼你需要的是.first(它不執行的SQL,直到你用類似.all,.first.each的東西來獲取記錄)。

雖然我認爲在單元測試中執行數據庫命令並不是最好的做法。你具體測試什麼?是否有你需要的用戶要保存在數據庫中,不能只是這樣做的理由:

let(:user){User.new(email: 'some email')} 
+0

在第一個示例中,右括號和括號是相反的。否則,這個船隻是現貨。 –

+1

Oh woops,感謝您指出了錯字 – nzifnab

+0

哈哈,現在也是最後一個例子。:)沒有概率,如果我有超過2個字符改變,我會自己編輯它。 –

0

ActiveRecord::Base#find_by實際上是where(options).first,但是這是一個整體的額外調用,你不必做。

Rails還提供了mildly deprecated「magic」find_by_<attribute>[and_<attribute>]方法,它使用method_missing解析出基於方法名稱的含義。雖然框架確實提供了這些,但我謹慎使用它們,因爲它們必然比「本地」方法慢,並且更能抵抗重構。

我會建議在一般情況下堅持使用find_by,並且會盡量避免在規格和測試中碰到數據庫。

factory_girl寶石提供創建其中叫聲也像記錄通過回答truepersisted?並提供id從數據庫返回的類的存根版本的方法。

或者,你可以建立一個新的記錄,但不保存:User.new(attribute: value, ...)和運行測試上:

it "does some things" do 
    user = User.new(attributes) 

    # make user do some things 

    expect(things).to have_happened 
end 
+0

其實'User.find_by_email(...)'樣式的發現者*不*棄用。請參閱deprecated_finders gem,以獲取最新版本的Rails中尚未棄用的內容和完整列表:https://github.com/rails/activerecord-deprecated_finders – nzifnab

+0

感謝您提供的信息,我錯了。我編輯了答案。 –

+0

哈,在他們的文檔中「輕度不推薦」。這到底意味着什麼?無論如何,即使魔術版本仍然存在,我可能更願意使用'.where'或'.find_by(email:'stuff')'。 – nzifnab