So there’s a Category that has many Expenses. The expenses for a category are destroyed when the category is destroyed. Elsewhere in my logic I would like to know if the category is removable based on whether it has any expenses and, if it does, whether any of the expenses it has are greater than zero.
has_many :items, :dependent => :destroy
def removable?
self.expenses.find(:first, :conditions => [‘total_cost > ?’, 0], :select => ‘id’).nil?
end
end
Should really get closer to the vest when protecting the data. So I added a callback to protect the category. Conveniently I can reuse the removable? method:
Let’s test it:
assert_difference(Category, :count, -1) do
@category.destroy
end
end
Yay!
Started
.
Finished in 1.950119 seconds.
1 tests, 3 assertions, 0 failures, 0 errors
And the other test:
create_expense(:total_cost => 50.00)
assert_no_difference(Category, :count) do
@category.destroy
end
end
NO!
Started
F
Finished in 1.965099 seconds.
1) Failure:
test_should_not_destroy__when_not_removable(CategoryTest)
method assert_no_difference in test_helper.rb at line 58
method test_should_not_destroy__when_not_removable in category_test.rb at line 66
<8> expected but was
<7>.
1 tests, 2 assertions, 1 failures, 0 errors
What the crap? Apparently the conditional in my removable? method must be working within the transactional space of the destroy call. See, a category has many expenses, set with :dependent => :destroy. In terms of the transaction, all of my expenses have already been destroyed and the category is indeed removable.
If I were to work entirely in memory, things come out alright.
private
def check_expenses_total
self.expenses.inject(0){ |sum, expense| sum + expense.total_cost } <= 0
end
So the lesson, I suppose, is be careful how DB-interactive you’re being in your destroy callbacks. Oh, and test.
(Another weird thing. self.expenses.sum(&:total_cost) didn’t seem to work. I had to use inject.)
Technorati Tags: Ruby, Rails, programming
Related posts:






