Following 2 statements look identical to me, however the first one
returns
only one object but the second one returns correctly an array of 4
objects.
What is happening here is simple, I get all the Grade objects (1st one
using Grade.find(:all) and second one using Grade.all), and then filter
out
all the grade objects where they have worksheets assigned to them.
@grades = Grade.find(:all){|grade| Worksheet.find(:all,:conditions=>
[‘grade_id =?’,grade.id]).count > 0}
*
*
@grades = Grade.all {|grade| Worksheet.find(:all,:conditions=>
[‘grade_id =?’,grade.id]).count > 0}
Can somebody explain why the results would be different for these 2
statements.
I don’t have rails in front of me, but looks like there may be a problem
with implied parentheses. Have you tried things like:
@grades = Grade.all() {|grade| Worksheet.find(:all,:conditions=>
[‘grade_id =?’,grade.id]).count > 0} *
*
Again I can’t test so not sure if that helps
The find method takes the option hash as the last parameter. Either use
Model.all(options) or Model.find(:all, options)
The correct code is:
@grades = Grade.find(:all, {|grade| Worksheet.find(:all,:conditions=>
[‘grade_id =?’,grade.id (http://grade.id)]).count > 0})
Dheeraj K.
Thanks Matt, Your alternative method on how to best get the data
definitely
is a much optimized solution then what I was using, I am not using that
and
everything works great.
However, I am still confused on one part.
as per my understanding
Grade.find(:all)
and
*Grade.all *
both should return an array of Grade objects, so how are the results
different if I just pass the objects through this block.
{|grade| Worksheet.find(:all,:conditions=> [‘grade_id
=?’,grade.id]).count
0}
Thanks again for the help.
On Thursday, 19 April 2012 22:14:51 UTC-4, Dheeraj K. wrote:
Um, no. That won’t even parse.
@grades = Grade.find(:all){|grade| Worksheet.find(:all,:conditions=>
[‘grade_id =?’,grade.id]).count > 0}
*
*
@grades = Grade.all {|grade| Worksheet.find(:all,:conditions=>
[‘grade_id =?’,grade.id]).count > 0}
There are two things going on here:
-
in the first statement, find(:all) acts like Enumerable#find when
passed
a block. Each of the found objects is passed to the block and the first
one
that returns a truthy value is returned.
-
in the second statement, all doesn’t call the block so you get exactly
the same results you would have without a block at all.
If this is an operation you do a lot in your app, you may want to check
out
the :counter_cache option of belongs_to, which will allow you to write
this
(correctly) as:
@grades = Grade.where(‘worksheets_count > 0’).all
Also note that if counts are all you’re looking for, you should avoid
doing
a find(:all) on them (as on Worksheet above); the count method on the
model
class can do this much more efficiently (with a SQL COUNT statement,
rather
than loading a bunch of objects and then counting them).
–Matt J.
On Friday, 20 April 2012 10:54:13 UTC-4, Ankur Jain wrote:
Grade.find(:all)
A block by itself doesn’t do ANYTHING - it’s entirely dependent on the
function it’s passed to. For instance:
def hello(who)
puts “Hello #{who}”
end
hello(‘World’) # prints “Hello World”
hello(‘World’) { |x| puts ‘WAT’ } # prints “Hello World” - doesn’t do
anything with the block
The case you encountered with find(:all) was specifically coded to use
the
block just like Enumerable#find:
a = [1,2,3,4]
a.find { |x| x > 2 } # => returns 3, the first value in the array that
the
block returns a truthy value for
–Matt J.