**控制器
puts merchants.first.is_blocked // 1
Merchant.update_all( {:is_blocked => 0}, "mch_id IN (#{@merchants.map(&:mch_id).join(",")})" )
puts merchants.first.is_blocked // 0, so it works
** rspec
expect {
get :update_merchants, params
}.to change { merchant_1.is_blocked }.from(1).to(0)
// result should have been changed to 0, but is now 1
我不知道为什么" update_all"方法在控制器中工作,并且在rspec中不起作用
答案 0 :(得分:4)
首先,你的update_all行非常讨厌。假设@merchants
是一个AREL查询,其中包含查找要更新的商家所需的条件,请考虑将其转换为:
@merchants.update_all(is_blocked: 0)
如果@merchants只是一个记录数组,那么请使用:
Merchant.where(id: @merchants.map(&:id)).update_all(is_blocked: 0)
其次,GET
请求从不修改数据库。请考虑将此更改为PUT
请求。
最后,如果在调用方法之前创建/获取了merchant_1
实例变量,则测试仍具有预更改值。您需要重新获取它,或者在您看到更新的值之前在其上调用reload
。
expect {
get :update_merchants, params
}.to change { merchant_1.reload.is_blocked }.from(1).to(0)
答案 1 :(得分:1)
您更新所有商家的is_blocked
属性的电话应如下所示:
Merchant.where(id: @merchants.map(&:id)).update_all(is_blocked: 0)
要在@ Jon的答案评论中回答您的问题(关于update_all
和update_attributes
之间的区别):
update_all
将直接在数据库中运行一个SQL查询来更新数据。update_attributes
为每个运行它的对象实例运行一个SQL查询。也就是说,update_all
使用它时效率更高,因为数据库可以完成所有工作,并且擅长大规模UPDATE
操作(不像循环遍历Ruby数组并运行)每条记录的单独SQL查询。)
然后,您需要确保在规范中重新加载merchant_1
以破坏该对象上的Rails的请求级查询缓存:
expect {
get :update_merchants, params
}.to change { merchant_1.reload.is_blocked }.from(1).to(0)