On Monday, 29 September 2014 23:15:36 UTC-4, Austin York wrote:
>
> In a todo list-style app, I have the following ActiveRecord model method:
>
> class Task < ActiveRecord::Base
>   # ...
>   def project_name
>     project.tasks.length > 0 ? "#{project.name} - #{name}" : project.name
>   end
> end
>
> The idea is to provide additional project information if there are one or 
> more tasks on the project.
>
> However, when invoked regularly on views this creates performance concerns 
> (especially with a growing data set).
>
> What is the best way to optimize this query so that it doesn't create N+1 
> query type issues when invoked from "each" loops in the view?
>

+1 what MichaƂ said about eager-loading. One additional tricky thing: 
prefer `size` over `length` for associations and relations. In plain Ruby, 
`size`, `length` and `count` are more or less identical - but for 
ActiveRecord collections they have slightly different meanings:

* `length` is the most straightforward: it's ALWAYS the number of records 
in the collection. If the collection isn't currently loaded, calling 
`length` on it will trigger a SQL query to load all the records.

* `count` is the opposite: it ALWAYS runs a SQL query. It doesn't load 
records, it uses SQL's `COUNT()` function. It can also return things that 
aren't numbers; doing `Task.group(:project_id).count` will give you back a 
hash with `project_id`s as keys and the number of matching tasks as values.

* `size` is the middle: if the collection is loaded, it works like 
`length`. Otherwise it works like `count`...

--Matt Jones

-- 
You received this message because you are subscribed to the Google Groups "Ruby 
on Rails: Talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/rubyonrails-talk/e6771c47-1c12-4e5a-8fe6-73af4d7b26e3%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to