Reputation: 431
** controller
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
i don't know the reason why "update_all" method works in controller and doesn't work in rspec
Upvotes: 3
Views: 1829
Reputation: 10918
Firstly, your update_all line is pretty nasty. Assuming @merchants
is an AREL query with the conditions required to locate the merchants you want to update, please consider converting it to this:
@merchants.update_all(is_blocked: 0)
If @merchants is simply an array of records, then use this:
Merchant.where(id: @merchants.map(&:id)).update_all(is_blocked: 0)
Secondly, a GET
request should NEVER modify the database. Consider changing this to a PUT
request.
Finally, if your merchant_1
instance variable was created/fetched before calling your method, your test still has the pre-change value. You either need to re-fetch it, or call reload
on it before you'll see the updated values.
expect {
get :update_merchants, params
}.to change { merchant_1.reload.is_blocked }.from(1).to(0)
Upvotes: 6
Reputation: 18090
Your call to update the is_blocked
attribute on all merchants should read like this:
Merchant.where(id: @merchants.map(&:id)).update_all(is_blocked: 0)
To answer your question in your comment on @Jon's answer (about the difference between update_all
and update_attributes
):
update_all
will run one SQL query directly in the database to update the data.update_attributes
runs one SQL query per object instance that you run it on.That said, update_all
is much more efficient when you use it because the database does all of the work, and it's good at mass UPDATE
operations like that (unlike looping through a Ruby array and running individual SQL queries for each record).
Then you need to make sure that you're reloading your merchant_1
in your spec to bust Rails's request-level query cache on that object:
expect {
get :update_merchants, params
}.to change { merchant_1.reload.is_blocked }.from(1).to(0)
Upvotes: 1