[英]Testing an association model helper method rails rspec
我有兩個模型, User
和Account
。
# account.rb
belongs_to :user
# user.rb
has_one :account
Account
具有屬性name
。 在我看來,我已經多次調用current_user.account.name
,並且聽說這不是一種很好的方法。 所以我非常快,我在user.rb
創建了以下方法
def account_name
self.account.name
end
因此,現在在我看來,我可以簡單地調用current_user.account_name
,並且如果關聯發生更改,我只會在一個地方進行更新。 但是我的問題是,我可以測試這種方法嗎? 如果可以,如何在沒有任何神秘客人的情況下進行測試?
我同意current_user.account.name沒什么問題-盡管Sandi Metz會告訴我們“用戶對帳戶了解太多”,這是您無法避免使用Active Record的事情。
如果發現您在整個User模型中都使用了許多這些方法,則可以使用rails委托方法:
delegate :name, :to => :account, :prefix => true
使用:prefix => true選項將在用戶模型中將該方法添加為account_name。 在這種情況下,我假設您可以在方法上編寫一個非常簡單的單元測試,以使其返回某些信息,以防萬一帳戶中的屬性會更改您的測試失敗,因此您將需要更新委托方法。
我個人認為沒有任何理由要這樣做。 只需使用current_user.account.name。
如果您擔心效率,請讓current_user返回一個加入帳戶的用戶。
這將有點題外話。 因此,如果沒有意思或沒有幫助,請提前道歉。
TL; DR:不要在您的視圖中放入模型知識。 使您的控制器保持瘦身。 這就是我一直在做的事情。
在我當前的項目中,我一直在努力確保我的視圖對系統其余部分完全一無所知(以減少耦合)。 這樣,如果您決定更改實現方式(例如current_user.account.name
與current_user.account_name
),則無需進入視圖並進行更改。
每個控制器操作都提供一個@results
哈希,其中包含視圖需要正確呈現的所有內容。 @results
哈希的結構本質上是視圖和控制器之間的協定。
因此,在我的控制器中, @results
可能類似於{current_user: {account: {name: 'foo'}}}
。 在我看來,我會做類似@results[:current_user][:account][:name]
。 我喜歡使用HashWithIndifferentAccess
所以我也可以執行@results['current_user']['account']['name']
且不會發生異常或行為異常。
另外,我一直在將盡可能多的邏輯從控制器移到服務對象(我稱它們為“管理器”)中。 我發現我的經理(即PORO)比控制器要容易得多。 因此,我可能有:
# app/controllers/some_controller.rb
class SomeController
def create
@results = SomeManager.create(params)
if @results[:success]
# happy routing
else
# sad routing
end
end
end
現在,我的控制器非常苗條,除了路由之外不包含任何邏輯。 他們對我的模型一無所知。 (實際上,幾乎所有的控制器動作在基本上相同的六行代碼中看起來都完全相同。)同樣,我喜歡這樣做是因為它會產生分離。
當然,我需要經理:
#app/managers/some_manager.rb
class SomeManager
class << self
def create(params)
# do stuff that ends up creating the @results hash
# if things went well, the return will include success: true
# if things did not go well, the return will not include a :success key
end
end
end
因此,實際上, @results
的結構是視圖和管理器之間的契約,而不是視圖和控制器之間的契約。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.