tag:blogger.com,1999:blog-4937488729022245645.post-58049083795920312002008-07-06T21:52:00.005-05:002008-07-06T22:05:39.834-05:002008-07-06T22:05:39.834-05:00named scopes pwns will_paginate<style type="text/css"> /* Stylesheet generated from TextMate theme * * Mac Classic * * */ /* Mostly to improve view within the TextMate HTML viewer */ body { margin: 0; padding: 0; } pre.textmate-source { margin: 0; padding: 0 0 0 2px; font-family: Monaco, monospace; font-size: 11px; line-height: 1.3em; word-wrap: break-word; white-space: pre; white-space: pre-wrap; white-space: -moz-pre-wrap; white-space: -o-pre-wrap; } pre.textmate-source.mac_classic { color: #000000; background-color: #FFFFFF; } pre.textmate-source .linenum { width: 75px; padding: 0.1em 1em 0.2em 0; color: #888; background-color: #eee; } pre.textmate-source.mac_classic span { padding-top: 0.2em; padding-bottom: 0.1em; } pre.textmate-source.mac_classic ::selection { background-color: rgba(77, 151, 255, 0.33); } /* Comment */ pre.textmate-source.mac_classic .comment { color: #0066FF; font-style: italic; } /* Keyword */ pre.textmate-source.mac_classic .keyword, pre.textmate-source.mac_classic .storage { color: #0000FF; font-weight: bold; } /* Number */ pre.textmate-source.mac_classic .constant_numeric { color: #0000CD; } /* User-defined constant */ pre.textmate-source.mac_classic .constant { color: #C5060B; font-weight: bold; } /* Built-in constant */ pre.textmate-source.mac_classic .constant_language { color: #585CF6; font-weight: bold; } /* Variable */ pre.textmate-source.mac_classic .variable_language, pre.textmate-source.mac_classic .variable_other { color: #318495; } /* String */ pre.textmate-source.mac_classic .string { color: #036A07; } /* String interpolation */ pre.textmate-source.mac_classic .constant_character_escape, pre.textmate-source.mac_classic .string .source { color: #26B31A; } /* Preprocessor line */ pre.textmate-source.mac_classic .meta_preprocessor { color: #1A921C; } /* Preprocessor directive */ pre.textmate-source.mac_classic .keyword_control_import { color: #0C450D; font-weight: bold; } /* Function name */ pre.textmate-source.mac_classic .entity_name_function, pre.textmate-source.mac_classic .support_function_any-method { color: #0000A2; font-weight: bold; } /* Type name */ pre.textmate-source.mac_classic .entity_name_type { text-decoration: underline; } /* Inherited class name */ pre.textmate-source.mac_classic .entity_other_inherited-class { font-style: italic; } /* Function parameter */ pre.textmate-source.mac_classic .variable_parameter { font-style: italic; } /* Function argument and result types */ pre.textmate-source.mac_classic .storage_type_method { color: #70727E; } /* Section */ pre.textmate-source.mac_classic .meta_section .entity_name_section, pre.textmate-source.mac_classic .declaration_section .entity_name_section { font-style: italic; } /* Library function */ pre.textmate-source.mac_classic .support_function { color: #3C4C72; font-weight: bold; } /* Library object */ pre.textmate-source.mac_classic .support_class, pre.textmate-source.mac_classic .support_type { color: #6D79DE; font-weight: bold; } /* Library constant */ pre.textmate-source.mac_classic .support_constant { color: #06960E; font-weight: bold; } /* Library variable */ pre.textmate-source.mac_classic .support_variable { color: #21439C; font-weight: bold; } /* JS: Operator */ pre.textmate-source.mac_classic .keyword_operator_js { color: #687687; } /* Invalid */ pre.textmate-source.mac_classic .invalid { color: #FFFFFF; background-color: #990000; } /* Invalid trailing whitespace */ pre.textmate-source.mac_classic .invalid_deprecated_trailing-whitespace { background-color: #FFD0D0; } /* Embedded source */ pre.textmate-source.mac_classic .text .source, pre.textmate-source.mac_classic .string_unquoted { background-color: rgba(0, 0, 0, 0.05); } /* Embedded embedded source */ pre.textmate-source.mac_classic .text .source .string_unquoted, pre.textmate-source.mac_classic .text .source .text .source { background-color: rgba(0, 0, 0, 0.06); } /* Markup XML declaration */ pre.textmate-source.mac_classic .meta_tag_preprocessor_xml { color: #68685B; } /* Markup DOCTYPE */ pre.textmate-source.mac_classic .meta_tag_sgml_doctype, pre.textmate-source.mac_classic .meta_tag_sgml_doctype .entity, pre.textmate-source.mac_classic .meta_tag_sgml_doctype .string, pre.textmate-source.mac_classic .meta_tag_preprocessor_xml, pre.textmate-source.mac_classic .meta_tag_preprocessor_xml .entity, pre.textmate-source.mac_classic .meta_tag_preprocessor_xml .string { color: #888888; } /* Markup DTD */ pre.textmate-source.mac_classic .string_quoted_docinfo_doctype_DTD { font-style: italic; } /* Markup tag */ pre.textmate-source.mac_classic .meta_tag, pre.textmate-source.mac_classic .declaration_tag { color: #1C02FF; } /* Markup name of tag */ pre.textmate-source.mac_classic .entity_name_tag { font-weight: bold; } /* Markup tag attribute */ pre.textmate-source.mac_classic .entity_other_attribute-name { font-style: italic; } /* Markup: Heading */ pre.textmate-source.mac_classic .markup_heading { color: #0C07FF; font-weight: bold; } /* Markup: Quote */ pre.textmate-source.mac_classic .markup_quote { color: #000000; font-style: italic; } /* Markup: List */ pre.textmate-source.mac_classic .markup_list { color: #B90690; } </style> <p><tt>will_paginate</tt> has its place. It's good for paginating when your queries are simple. My queries usually aren't simple, are yours? I noticed recently that one of my pages was taking a long time to display, around 1.9 seconds. I tracked it down to the <tt>will_paginate</tt>.</p> <p>The problem is that <tt>will_paginate</tt> takes a single hash of ActiveRecord::Base#find arguments. That means if your query is really complex, then it's going to use that same complex query for both the result set and the count.</p> <p>This is more or less what I was doing with <tt>will_paginate</tt> that it was choking on.</p> <pre class="textmate-source mac_classic"><span class="source source_ruby source_ruby_rails"><span class="meta meta_rails meta_rails_model"><span class="meta meta_class meta_class_ruby"><span class="keyword keyword_control keyword_control_class keyword_control_class_ruby">class</span> <span class="entity entity_name entity_name_type entity_name_type_class entity_name_type_class_ruby">Post<span class="entity entity_other entity_other_inherited-class entity_other_inherited-class_ruby"> <span class="punctuation punctuation_separator punctuation_separator_inheritance punctuation_separator_inheritance_ruby">&lt;</span> ActiveRecord::Base</span></span></span> <span class="variable variable_other variable_other_constant variable_other_constant_ruby">STATUS_OK</span> <span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby">=</span> <span class="constant constant_numeric constant_numeric_ruby">1</span> <span class="support support_function support_function_activesupport support_function_activesupport_rails">cattr_accessor</span> <span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>per_page</span> per_page <span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby">=</span> <span class="constant constant_numeric constant_numeric_ruby">15</span> <span class="support support_function support_function_activerecord support_function_activerecord_rails">has_many</span> <span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>watchers</span><span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> <span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">...</span> </span><span class="keyword keyword_control keyword_control_ruby">end</span> <span class="meta meta_rails meta_rails_controller"><span class="meta meta_class meta_class_ruby"><span class="keyword keyword_control keyword_control_class keyword_control_class_ruby">class</span> <span class="entity entity_name entity_name_type entity_name_type_class entity_name_type_class_ruby">PostsController<span class="entity entity_other entity_other_inherited-class entity_other_inherited-class_ruby"> <span class="punctuation punctuation_separator punctuation_separator_inheritance punctuation_separator_inheritance_ruby">&lt;</span> ApplicationController</span></span></span> <span class="meta meta_function meta_function_method meta_function_method_without-arguments meta_function_method_without-arguments_ruby"><span class="keyword keyword_control keyword_control_def keyword_control_def_ruby">def</span> <span class="entity entity_name entity_name_function entity_name_function_ruby">index</span></span> page_no <span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby">=</span> <span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">(</span>params<span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">[</span><span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>page</span><span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">]</span> <span class="keyword keyword_operator keyword_operator_logical keyword_operator_logical_ruby">&amp;&amp;</span> params<span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">[</span><span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>page</span><span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">]</span><span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>to_i<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">)</span> <span class="keyword keyword_operator keyword_operator_logical keyword_operator_logical_ruby">||</span> <span class="constant constant_numeric constant_numeric_ruby">1</span> <span class="variable variable_other variable_other_readwrite variable_other_readwrite_instance variable_other_readwrite_instance_ruby"><span class="punctuation punctuation_definition punctuation_definition_variable punctuation_definition_variable_ruby">@</span>posts</span> <span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby">=</span> <span class="support support_class support_class_ruby">Post</span><span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>paginate <span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>conditions</span> <span class="punctuation punctuation_separator punctuation_separator_key-value">=&gt;</span> <span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">[</span><span class="string string_quoted string_quoted_double string_quoted_double_ruby"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby">"</span>posts.status_id = ?<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby">"</span></span><span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> <span class="support support_class support_class_ruby">Post</span><span class="punctuation punctuation_separator punctuation_separator_other punctuation_separator_other_ruby">::</span><span class="variable variable_other variable_other_constant variable_other_constant_ruby">STATUS_OK</span><span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">]</span><span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> <span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>order</span> <span class="punctuation punctuation_separator punctuation_separator_key-value">=&gt;</span> <span class="string string_quoted string_quoted_single string_quoted_single_ruby"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby">'</span>group_id DESC, checksum<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby">'</span></span><span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> <span class="comment comment_line comment_line_number-sign comment_line_number-sign_ruby"><span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby">#</span> don't ask, it's complicated </span> <span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>include</span> <span class="punctuation punctuation_separator punctuation_separator_key-value">=&gt;</span> <span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>watchers</span><span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> <span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>page</span> <span class="punctuation punctuation_separator punctuation_separator_key-value">=&gt;</span> page_no <span class="keyword keyword_control keyword_control_ruby">end</span> </span><span class="keyword keyword_control keyword_control_ruby">end</span></span></pre> <br/> <p>The counting sql it makes out of that query does an outer join on <tt>watchers</tt> and selects distinct <tt>posts.id</tt>. Ouch. So the obvious solution is to simply do the count and result set queries ourselves. No biggie, but let's use named scopes to pretty things up.</p> <pre class="textmate-source mac_classic"><span class="source source_ruby source_ruby_rails"><span class="meta meta_rails meta_rails_model"><span class="meta meta_class meta_class_ruby"><span class="keyword keyword_control keyword_control_class keyword_control_class_ruby">class</span> <span class="entity entity_name entity_name_type entity_name_type_class entity_name_type_class_ruby">Post<span class="entity entity_other entity_other_inherited-class entity_other_inherited-class_ruby"> <span class="punctuation punctuation_separator punctuation_separator_inheritance punctuation_separator_inheritance_ruby">&lt;</span> ActiveRecord::Base</span></span></span> <span class="variable variable_other variable_other_constant variable_other_constant_ruby">STATUS_OK</span> <span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby">=</span> <span class="constant constant_numeric constant_numeric_ruby">1</span> <span class="support support_function support_function_activesupport support_function_activesupport_rails">cattr_accessor</span> <span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>per_page</span> per_page <span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby">=</span> <span class="constant constant_numeric constant_numeric_ruby">15</span> <span class="support support_function support_function_activerecord support_function_activerecord_rails">has_many</span> <span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>watchers</span><span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> <span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">...</span> named_scope <span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>ok</span><span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> <span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>conditions</span> <span class="punctuation punctuation_separator punctuation_separator_key-value">=&gt;</span> <span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_ruby">{</span><span class="string string_quoted string_quoted_double string_quoted_double_ruby"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby">"</span>posts.status_id<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby">"</span></span> <span class="punctuation punctuation_separator punctuation_separator_key-value">=&gt;</span> <span class="support support_class support_class_ruby">Post</span><span class="punctuation punctuation_separator punctuation_separator_other punctuation_separator_other_ruby">::</span><span class="variable variable_other variable_other_constant variable_other_constant_ruby">STATUS_OK</span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_ruby">}</span> named_scope <span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>recent</span><span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> <span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>order</span> <span class="punctuation punctuation_separator punctuation_separator_key-value">=&gt;</span> <span class="string string_quoted string_quoted_double string_quoted_double_ruby"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby">"</span>group_id DESC, checksum<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby">"</span></span> named_scope <span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>paginate</span><span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> lambda <span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_ruby">{</span><span class="meta meta_syntax meta_syntax_ruby meta_syntax_ruby_start-block"> </span><span class="punctuation punctuation_separator punctuation_separator_variable punctuation_separator_variable_ruby">|</span><span class="variable variable_other variable_other_block variable_other_block_ruby">page_no</span><span class="punctuation punctuation_separator punctuation_separator_variable punctuation_separator_variable_ruby">|</span> <span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_ruby">{</span><span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>offset</span> <span class="punctuation punctuation_separator punctuation_separator_key-value">=&gt;</span> <span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_ruby">{</span><span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">(</span>page_no<span class="keyword keyword_operator keyword_operator_arithmetic keyword_operator_arithmetic_ruby">-</span><span class="constant constant_numeric constant_numeric_ruby">1</span><span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">)</span><span class="keyword keyword_operator keyword_operator_arithmetic keyword_operator_arithmetic_ruby">*</span>per_page<span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_ruby">}</span><span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> <span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>limit</span> <span class="punctuation punctuation_separator punctuation_separator_key-value">=&gt;</span> per_page<span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_ruby">}</span> <span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_ruby">}</span> </span><span class="keyword keyword_control keyword_control_ruby">end</span> <span class="meta meta_rails meta_rails_controller"><span class="meta meta_class meta_class_ruby"><span class="keyword keyword_control keyword_control_class keyword_control_class_ruby">class</span> <span class="entity entity_name entity_name_type entity_name_type_class entity_name_type_class_ruby">PostsController<span class="entity entity_other entity_other_inherited-class entity_other_inherited-class_ruby"> <span class="punctuation punctuation_separator punctuation_separator_inheritance punctuation_separator_inheritance_ruby">&lt;</span> ApplicationController</span></span></span> <span class="meta meta_function meta_function_method meta_function_method_without-arguments meta_function_method_without-arguments_ruby"><span class="keyword keyword_control keyword_control_def keyword_control_def_ruby">def</span> <span class="entity entity_name entity_name_function entity_name_function_ruby">index</span></span> page_no <span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby">=</span> <span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">(</span>params<span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">[</span><span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>page</span><span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">]</span> <span class="keyword keyword_operator keyword_operator_logical keyword_operator_logical_ruby">&amp;&amp;</span> params<span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">[</span><span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>page</span><span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">]</span><span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>to_i<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">)</span> <span class="keyword keyword_operator keyword_operator_logical keyword_operator_logical_ruby">||</span> <span class="constant constant_numeric constant_numeric_ruby">1</span> <span class="variable variable_other variable_other_readwrite variable_other_readwrite_instance variable_other_readwrite_instance_ruby"><span class="punctuation punctuation_definition punctuation_definition_variable punctuation_definition_variable_ruby">@</span>posts</span> <span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby">=</span> <span class="support support_class support_class_ruby">Post</span><span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>ok<span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>recent<span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>paginate<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">(</span>page_no<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">)</span><span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>all<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">(</span><span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>include</span> <span class="punctuation punctuation_separator punctuation_separator_key-value">=&gt;</span> <span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>watchers</span><span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">)</span> <span class="variable variable_other variable_other_readwrite variable_other_readwrite_instance variable_other_readwrite_instance_ruby"><span class="punctuation punctuation_definition punctuation_definition_variable punctuation_definition_variable_ruby">@</span>post_count</span> <span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby">=</span> <span class="support support_class support_class_ruby">Post</span><span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>ok<span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>count <span class="keyword keyword_control keyword_control_ruby">end</span> </span><span class="keyword keyword_control keyword_control_ruby">end</span></span></pre> <br/> <p>Pretty slick... and since we're doing the pagination "explicitly", we know that the counting is as simple as it needs to be. Let's take a look at the benchmarks, before and after.</p> <pre class="textmate-source mac_classic"><span class="source source_sql source_sql_ruby"><span class="comment comment_line comment_line_number-sign comment_line_number-sign_sql"><span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_sql">#</span> The SQL calls generated by will_paginate </span>Post Load (<span class="constant constant_numeric constant_numeric_sql">0</span>.<span class="constant constant_numeric constant_numeric_sql">341523</span>) <span class="keyword keyword_other keyword_other_DML keyword_other_DML_sql">SELECT</span> <span class="keyword keyword_operator keyword_operator_star keyword_operator_star_sql">*</span> <span class="keyword keyword_other keyword_other_DML keyword_other_DML_sql">FROM</span> <span class="string string_quoted string_quoted_double string_quoted_double_sql"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_sql">"</span>posts"</span> <span class="keyword keyword_other keyword_other_DML keyword_other_DML_sql">WHERE</span> (<span class="constant constant_other constant_other_database-name constant_other_database-name_sql">post</span>.<span class="constant constant_other constant_other_table-name constant_other_table-name_sql">status_id</span> <span class="keyword keyword_operator keyword_operator_comparison keyword_operator_comparison_sql">=</span> <span class="constant constant_numeric constant_numeric_sql">1</span>) <span class="keyword keyword_other keyword_other_DML keyword_other_DML_sql">ORDER BY</span> group_id <span class="keyword keyword_other keyword_other_order keyword_other_order_sql">DESC</span>, checksum <span class="keyword keyword_other keyword_other_DML keyword_other_DML_sql">LIMIT</span> <span class="constant constant_numeric constant_numeric_sql">15</span> OFFSET <span class="constant constant_numeric constant_numeric_sql">0</span> Watcher Load (<span class="constant constant_numeric constant_numeric_sql">0</span>.<span class="constant constant_numeric constant_numeric_sql">005799</span>) <span class="keyword keyword_other keyword_other_DML keyword_other_DML_sql">SELECT</span> <span class="string string_quoted string_quoted_double string_quoted_double_sql"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_sql">"</span>watchers"</span>.<span class="keyword keyword_operator keyword_operator_star keyword_operator_star_sql">*</span> <span class="keyword keyword_other keyword_other_DML keyword_other_DML_sql">FROM</span> <span class="string string_quoted string_quoted_double string_quoted_double_sql"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_sql">"</span>watchers"</span> <span class="keyword keyword_other keyword_other_DML keyword_other_DML_sql">WHERE</span> (<span class="string string_quoted string_quoted_double string_quoted_double_sql"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_sql">"</span>watchers"</span>.page_id <span class="keyword keyword_other keyword_other_data-integrity keyword_other_data-integrity_sql">IN</span> (...)) <span class="keyword keyword_other keyword_other_DML keyword_other_DML_sql">ORDER BY</span> id SQL (<span class="constant constant_numeric constant_numeric_sql">1</span>.<span class="constant constant_numeric constant_numeric_sql">335042</span>) <span class="keyword keyword_other keyword_other_DML keyword_other_DML_sql">SELECT</span> <span class="support support_function support_function_aggregate support_function_aggregate_sql">count</span>(DISTINCT <span class="string string_quoted string_quoted_double string_quoted_double_sql"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_sql">"</span>posts"</span>.id) <span class="keyword keyword_other keyword_other_alias keyword_other_alias_sql">AS</span> count_all <span class="keyword keyword_other keyword_other_DML keyword_other_DML_sql">FROM</span> <span class="string string_quoted string_quoted_double string_quoted_double_sql"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_sql">"</span>posts"</span> <span class="keyword keyword_other keyword_other_DML keyword_other_DML_sql">LEFT OUTER JOIN</span> <span class="string string_quoted string_quoted_double string_quoted_double_sql"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_sql">"</span>watchers"</span> <span class="keyword keyword_other keyword_other_DDL keyword_other_DDL_create keyword_other_DDL_create_II keyword_other_DDL_create_II_sql">ON</span> <span class="constant constant_other constant_other_database-name constant_other_database-name_sql">watchers</span>.<span class="constant constant_other constant_other_table-name constant_other_table-name_sql">post_id</span> <span class="keyword keyword_operator keyword_operator_comparison keyword_operator_comparison_sql">=</span> <span class="constant constant_other constant_other_database-name constant_other_database-name_sql">posts</span>.<span class="constant constant_other constant_other_table-name constant_other_table-name_sql">id</span> <span class="keyword keyword_other keyword_other_DML keyword_other_DML_sql">WHERE</span> (<span class="constant constant_other constant_other_database-name constant_other_database-name_sql">posts</span>.<span class="constant constant_other constant_other_table-name constant_other_table-name_sql">status_id</span> <span class="keyword keyword_operator keyword_operator_comparison keyword_operator_comparison_sql">=</span> <span class="constant constant_numeric constant_numeric_sql">1</span>) <span class="comment comment_line comment_line_number-sign comment_line_number-sign_sql"><span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_sql">#</span> The SQL calls generated when we "manually paginate". </span>Post Load (<span class="constant constant_numeric constant_numeric_sql">0</span>.<span class="constant constant_numeric constant_numeric_sql">350336</span>) <span class="keyword keyword_other keyword_other_DML keyword_other_DML_sql">SELECT</span> <span class="keyword keyword_operator keyword_operator_star keyword_operator_star_sql">*</span> <span class="keyword keyword_other keyword_other_DML keyword_other_DML_sql">FROM</span> <span class="string string_quoted string_quoted_double string_quoted_double_sql"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_sql">"</span>posts"</span> <span class="keyword keyword_other keyword_other_DML keyword_other_DML_sql">WHERE</span> (<span class="string string_quoted string_quoted_double string_quoted_double_sql"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_sql">"</span>posts"</span>.<span class="string string_quoted string_quoted_double string_quoted_double_sql"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_sql">"</span>status_id"</span> <span class="keyword keyword_operator keyword_operator_comparison keyword_operator_comparison_sql">=</span> <span class="constant constant_numeric constant_numeric_sql">1</span>) <span class="keyword keyword_other keyword_other_DML keyword_other_DML_sql">ORDER BY</span> group_id <span class="keyword keyword_other keyword_other_order keyword_other_order_sql">DESC</span>, checksum <span class="keyword keyword_other keyword_other_DML keyword_other_DML_sql">LIMIT</span> <span class="constant constant_numeric constant_numeric_sql">15</span> OFFSET <span class="constant constant_numeric constant_numeric_sql">0</span> Watcher Load (<span class="constant constant_numeric constant_numeric_sql">0</span>.<span class="constant constant_numeric constant_numeric_sql">004582</span>) <span class="keyword keyword_other keyword_other_DML keyword_other_DML_sql">SELECT</span> <span class="string string_quoted string_quoted_double string_quoted_double_sql"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_sql">"</span>watchers"</span>.<span class="keyword keyword_operator keyword_operator_star keyword_operator_star_sql">*</span> <span class="keyword keyword_other keyword_other_DML keyword_other_DML_sql">FROM</span> <span class="string string_quoted string_quoted_double string_quoted_double_sql"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_sql">"</span>watchers"</span> <span class="keyword keyword_other keyword_other_DML keyword_other_DML_sql">WHERE</span> (<span class="string string_quoted string_quoted_double string_quoted_double_sql"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_sql">"</span>watchers"</span>.post_id <span class="keyword keyword_other keyword_other_data-integrity keyword_other_data-integrity_sql">IN</span> (...)) <span class="keyword keyword_other keyword_other_DML keyword_other_DML_sql">ORDER BY</span> id SQL (<span class="constant constant_numeric constant_numeric_sql">0</span>.<span class="constant constant_numeric constant_numeric_sql">023346</span>) <span class="keyword keyword_other keyword_other_DML keyword_other_DML_sql">SELECT</span> <span class="support support_function support_function_aggregate support_function_aggregate_sql">count</span>(<span class="keyword keyword_operator keyword_operator_star keyword_operator_star_sql">*</span>) <span class="keyword keyword_other keyword_other_alias keyword_other_alias_sql">AS</span> count_all <span class="keyword keyword_other keyword_other_DML keyword_other_DML_sql">FROM</span> <span class="string string_quoted string_quoted_double string_quoted_double_sql"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_sql">"</span>posts"</span> <span class="keyword keyword_other keyword_other_DML keyword_other_DML_sql">WHERE</span> (<span class="string string_quoted string_quoted_double string_quoted_double_sql"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_sql">"</span>posts"</span>.<span class="string string_quoted string_quoted_double string_quoted_double_sql"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_sql">"</span>status_id"</span> <span class="keyword keyword_operator keyword_operator_comparison keyword_operator_comparison_sql">=</span> <span class="constant constant_numeric constant_numeric_sql">1</span>)</span></pre> <br/> <p>We save roughly 1.3 seconds by intelligently doing the counting. I really don't think using <tt>will_paginate</tt> buys you any cleaner code over using named scopes. Now all you have to do is implement a method similar to the <tt>will_paginate</tt> view helper and you can remove <tt>will_paginate</tt> from your project.</p>Christopher J. Bottarohttp://www.blogger.com/profile/14116593743589959438noreply@blogger.com