3

我正在阅读 6.3 版 Michael Hartel 的 rails 教程,需要 user_spec 模型的替代代码。他拥有的代码是:

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

看起来我可以使用 where,但不确定语法是否正确。我尝试了以下几种变体:

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

我确信这是一个非常简单的答案,但不能完全理解。

4

2 回答 2

4
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')}
于 2013-09-05T17:33:17.863 回答
1

ActiveRecord::Base#find_by是有效where(options).first的,但这是一个你不需要做的额外调用。

Rails 还提供了一些不推荐使用的“魔法”find_by_<attribute>[and_<attribute>]方法,这些方法用于method_missing根据方法的名称解析出其含义。虽然框架确实提供了这些,但我警告不要使用它们,因为它们必然比“本机”方法慢,并且更难以重构。

对于一般情况,我建议坚持使用find_by,并尽量避免在规范和测试中触及数据库。

factory_girl gem提供了一种方法来创建类的存根版本,该版本通过回答并true提供.persisted?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
于 2013-09-05T20:35:14.947 回答