# Code in layout files, and minimizing database usage

**URL:** <https://www.ruby-forum.com/t/code-in-layout-files-and-minimizing-database-usage/168977>\
**Category:** Rails\
**Created:** [May 28, 2009, 1:33am UTC](https://www.ruby-forum.com/t/code-in-layout-files-and-minimizing-database-usage/168977 "2009-05-28T01:33:28Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![bigdaddy71](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/bbe5ce/32.png) [@bigdaddy71](https://www.ruby-forum.com/u/bigdaddy71)\
**Post date:** [May 28, 2009, 1:33am UTC](https://www.ruby-forum.com/t/code-in-layout-files-and-minimizing-database-usage/168977/1 "2009-05-28T01:33:28Z")

</div>

So, I’m putting together a blog, and I want the posts on it to be easily  
browsable by date. So far I’ve given each post attributes for the month  
and year it was created. That way, when someone visits  
[example.com/blog/2008](http://example.com/blog/2008) Rails does a find\_all\_by\_year and displays and  
paginates the results - similarly, when someone visits  
[example.com/blog/2008/09](http://example.com/blog/2008/09) Rails does find\_all\_by\_year\_and\_month and does  
the same.

Now, I’m trying to change the blog layout so that it provides links to  
each month as well as the post count for that month. This would look  
something like:

August 2008 (24)  
September 2008 (33)  
October 2008 (17)

And so on. So, two questions:

#1 - What’s the best way to do this? The most direct method I see is to  
do a Post.find\_all\_by\_year\_and\_month(…).count for each month of each  
year, but that would be pretty abusive of the database, right?

#2 - How do I do this and remain MVC? The above display is happening in  
the layout, and I know I shouldn’t be getting very code-heavy in the  
view, but I don’t know where else to put this kind of functionality.

Thanks!  
Chris

---

<div class="post-metadata">

**Author:** ![bigdaddy71](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/bbe5ce/32.png) [@bigdaddy71](https://www.ruby-forum.com/u/bigdaddy71)\
**Post date:** [May 28, 2009, 3:06am UTC](https://www.ruby-forum.com/t/code-in-layout-files-and-minimizing-database-usage/168977/2 "2009-05-28T03:06:41Z")

</div>

Ok, after some thinking and experimentation, I came up with:

\<% posts = Post.all(:select =\> “year, month”, :order =\> “year,  
month”).collect(&:attributes) %\>  
\<% (posts.first[“year”]…posts.last[“year”]).to\_a.reverse.each do |year|  
%\>

\<%= year %\>

 \<% posts\_by\_year = posts.select{|hash| hash["year"] == year} %\> 
 \<% (1..12).to\_a.reverse.each do |index| %\> \<% posts\_by\_month = posts\_by\_year.select{|hash| hash["month"] == ("%02d" % index)}%\> \<% unless posts\_by\_month.length == 0 %\> - \<%= link\_to "#{Date::MONTHNAMES[index]} #{year}", month\_path(year, ("%02d" % index)) %\> (\<%= posts\_by\_month.length %\>)
 \<% end %\> \<% end %\> 
\<% end %\>

It’s working well. It’s all still stuck in the view, but oh well. If  
anyone knows a better place, let me know.

---

<div class="post-metadata">

**Author:** ![bigdaddy71](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/bbe5ce/32.png) [@bigdaddy71](https://www.ruby-forum.com/u/bigdaddy71)\
**Post date:** [May 28, 2009, 5:57am UTC](https://www.ruby-forum.com/t/code-in-layout-files-and-minimizing-database-usage/168977/3 "2009-05-28T05:57:36Z")

</div>

Chris H. wrote:  
[…]

> It’s working well. It’s all still stuck in the view, but oh well.

That’s way too much logic to put in a view, even by my standards. 🙂

> If  
> anyone knows a better place, let me know.

The easiest refactoring would be to put it in a helper. Or perhaps you  
can get creative with a class method on Post.

## Best,

Marnen Laibow-Koser  
[http://www.marnen.org](http://www.marnen.org)  
removed\_email\_address@domain.invalid

---

<div class="post-metadata">

**Author:** ![bigdaddy71](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/bbe5ce/32.png) [@bigdaddy71](https://www.ruby-forum.com/u/bigdaddy71)\
**Post date:** [May 28, 2009, 10:04am UTC](https://www.ruby-forum.com/t/code-in-layout-files-and-minimizing-database-usage/168977/4 "2009-05-28T10:04:37Z")

</div>

Why do you want to load all the posts into memory? For doing a  
count, rely on SQL instead of Ruby. It is faster and more efficient.

Post.count(:conditions=\>“xxx”) translates into a select count(\*) from  
posts where “xxx”

When someone clicks on the month title, you can always do a query with  
a :limit to show the last 10 posts and a “all” link to show all posts  
in that month.

I would have class level functions in the Post model provide me  
information regarding count and data. The model alone knows how to  
get that data, other parts of the application have no need to dig into  
those details. This will ensure your app doesn’t break if you change  
the implementation of Post in the future.

---

<div class="post-metadata">

**Author:** ![bigdaddy71](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/bbe5ce/32.png) [@bigdaddy71](https://www.ruby-forum.com/u/bigdaddy71)\
**Post date:** [May 28, 2009, 9:18am UTC](https://www.ruby-forum.com/t/code-in-layout-files-and-minimizing-database-usage/168977/5 "2009-05-28T09:18:19Z")

</div>

On 28/05/2009, at 11:06 AM, Chris H. wrote:

> Ok, after some thinking and experimentation, I came up with:
> 
> \<% posts = Post.all(:select =\> “year, month”, :order =\> “year,  
> month”).collect(&:attributes) %\>

Any time you’re doing equalities against a model object (here Post),  
you could put it in the controller and assign it to an instance  
varaible.

Also I’m not sure why you’re getting the attributes of the objects,  
when you could be getting the objects by themselves.

controller:  
@posts = Post.all(:select =\> “year, month”, :order =\> “year DESC,  
month DESC”)

view:

\<% @posts.group\_by(&:year).each do |year, year\_of\_posts | %\>  
\<%= year %\>  
\<% year\_of\_posts.group\_by(&:month) do |month, month\_of\_posts| %\>  
\<% month\_of\_posts.each do |post| %\>  
\<%= "some data about the posts or links or whatever %\>  
\<% end %\>  
\<% end %\>  
\<% end %\>

obviously you should change this to be more in line with what you  
actually want (probably the inner each is unnecessary for your  
requirements.

Rather than reversing in ruby, use order with DESC sql fragment to get  
the data the way you want it from the database. This is what the  
database is good at.  
Also, have you thought of actually storing a datetime for the post,  
instead of doing all this crazy number stuff? Then you could use the  
strftime method on the datetime to print out the dates nicely. Much  
more elegant.

Julian.

* * *

Learn: [http://sensei.zenunit.com/](http://sensei.zenunit.com/)  
Last updated 20-May-09 (Rails, Basic Unix)  
Blog: [http://random8.zenunit.com/](http://random8.zenunit.com/)  
Twitter: [http://twitter.com/random8r](http://twitter.com/random8r)

---

<div class="post-metadata">

**Author:** ![bigdaddy71](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/bbe5ce/32.png) [@bigdaddy71](https://www.ruby-forum.com/u/bigdaddy71)\
**Post date:** [May 28, 2009, 10:24am UTC](https://www.ruby-forum.com/t/code-in-layout-files-and-minimizing-database-usage/168977/6 "2009-05-28T10:24:33Z")

</div>

On May 28, 9:03 am, Mukund [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> Why do you want to load all the posts into memory? For doing a  
> count, rely on SQL instead of Ruby. It is faster and more efficient.
> 
> Post.count(:conditions=\>“xxx”) translates into a select count(\*) from  
> posts where “xxx”

And you could even do Post.count(:all, :group =\> ‘year, month’ ) (and  
then cache that 🙂 )

Fred
