0

In my understanding the following ruby expressions should produce the same result.
Apparently I am missing something, this is a way too serious bug to go unnoticed...

# returns the number of ALL elements in the array
count = @quotation.quotation_items.count { |x| x.placement == current_placement}

# Does what I expect
count = (@quotation.quotation_items.find_all { |x| x.placement == current_placement }).length

quotation_items above is an ActiveRecord has_many association

3 Answers 3

2

#count does not take a block like that.

If you want to use conditions on a count, you would do:

@quotation.quotation_items.count(:conditions => "placement = #{current_placement}")

http://apidock.com/rails/ActiveRecord/Calculations/ClassMethods/count

Sign up to request clarification or add additional context in comments.

3 Comments

it is CollectionAssociation method, not Calculation (see link)
The ActiveRecord count always triggers a SELECT COUNT(...) on the db - it is not the same as the Enumerable#count
Remember conditions should be expressed as { x: y } or ['x=?', y] and never "x=#{y}" since the last one is a potential SQL injection hole.
1

If you're using ActiveRecord you need to keep in mind that there's a point where it's compiling conditions and clauses for a query and a point where you have a result set. Certain things only work in one mode or the other, though it tries to keep things pretty consistent regardless.

In your case you are expecting count to work like Enumerable, but that's still a database-level operator.

To fix that:

@quotation.quotation_items.where(placement: current_placement).count

That composes a query that counts only the things you need, something approximating:

SELECT COUNT(*) FROM quotation_items WHERE quotation_id=? AND placement=?

That's something that yields a single number and is considerably different than selecting every record, instantiating into models, then counting those using Enumerable.

Comments

0

Your usage of #count is incorrect.

I believe it doesn't accept a block. I'm not sure why it didn't return an error though.

you can use it like this :

count = @quotation.quotation_items.map{ |x| x.placement == current_placement}.count(true)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.