繁体   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