簡體   English   中英

測試關聯模型助手方法Rails RSpec

[英]Testing an association model helper method rails rspec

我有兩個模型, UserAccount

# 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。 在這種情況下,我假設您可以在方法上編寫一個非常簡單的單元測試,以使其返回某些信息,以防萬一帳戶中的屬性會更改您的測試失敗,因此您將需要更新委托方法。

  1. current_user.account.name沒有任何問題
  2. 將其稱為current_user.account.name或使current_user.account_name為其命名沒有區別
  3. 您可能沒有在模型中調用current_user,就像您說的那樣
  4. 如果您使用它,應該有一個規格

我個人認為沒有任何理由要這樣做。 只需使用current_user.account.name。

如果您擔心效率,請讓current_user返回一個加入帳戶的用戶。

這將有點題外話。 因此,如果沒有意思或沒有幫助,請提前道歉。

TL; DR:不要在您的視圖中放入模型知識。 使您的控制器保持瘦身。 這就是我一直在做的事情。

在我當前的項目中,我一直在努力確保我的視圖對系統其余部分完全一無所知(以減少耦合)。 這樣,如果您決定更改實現方式(例如current_user.account.namecurrent_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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM