2009-07-03 6 views
5

Hy les gars. J'ai créé une application de blog simple avec les actions habituelles de CRUD. J'ai également ajouté une nouvelle action dans le PostController appelée "archive" et une vue associée. Dans cette perspective, je veux ramener tous les messages de blog et de les regrouper par mois, en les affichant dans ce type de format:Ruby on Rails: regrouper les billets de blog par mois

March 
<ul> 
    <li>Hello World</li> 
    <li>Blah blah</li> 
    <li>Nothing to see here</li> 
    <li>Test post...</li> 
</ul> 

Febuary 
<ul> 
    <li>My hangover sucks</li> 
    ... etc ... 

Je ne peux pas pour la vie de me trouver la meilleure façon de le faire. En supposant que le modèle Post a les champs habituels title, content, created_at, quelqu'un peut-il m'aider avec la logique/code? Je suis très nouveau pour RoR alors s'il vous plaît garder avec moi :)

Répondre

31

group_by est une bonne méthode:

contrôleur:

def archive 
    #this will return a hash in which the month names are the keys, 
    #and the values are arrays of the posts belonging to such months 
    #something like: 
    #{ "February" => [#<Post 0xb5c836a0>,#<Post 0xb5443a0>], 
    # 'March' => [#<Post 0x43443a0>] } 
    @posts_by_month = Posts.find(:all).group_by { |post| post.created_at.strftime("%B") } 
end 

modèle de vue:

<% @posts_by_month.each do |monthname, posts| %> 
<%= monthname %> 
<ul> 
    <% posts.each do |post| %> 
    <li><%= post.title %></li> 
    <% end %> 
</ul> 
<% end %> 
+3

Ceci est plus lié à l'OP: * Vous pourriez vouloir regrouper par Année-Mois, car une fois qu'il a été reporté à l'année suivante (disons 2010), alors la section de Janvier aura les entrées de 2009 et 2010. * Vous souhaiterez peut-être trier les entrées de chaque mois par date (jour) pour vous assurer que la liste est chronologique. – BryanH

+2

Solution parfaite! Merci beaucoup :) –

+0

Palm slap moment, j'ai fait ma propre fonction group_by similaire pour l'affichage des groupes d'enregistrements dans mes vues. Content de l'avoir découvert. –

7

@Maximiliano Guzman

Bonne réponse! Merci d'avoir ajouté de la valeur à la communauté Rails. J'inclus ma source originale sur How to Create a Blog Archive with Rails, juste au cas où je massacrerais le raisonnement de l'auteur. Basé sur le blog, pour les nouveaux développeurs de Rails, j'ajouterais quelques suggestions.

D'abord, utilisez la fonction Active Records Posts.all pour renvoyer le jeu de résultats de publication pour une vitesse et une interopérabilité accrues. La méthode Posts.find (: all) est connue pour avoir des problèmes imprévus.

Enfin, dans la même veine, utilisez la méthode begin_of_month à partir des extensions de base ActiveRecord. Je trouve begin_of_month beaucoup plus lisible que strftime ("% B"). Bien sûr, le choix vous appartient.

Voici un exemple de ces suggestions. S'il vous plaît voir le billet original pour plus de détails:

contrôleurs/archives_controller.rb

def index 
    @posts = Post.all(:select => "title, id, posted_at", :order => "posted_at DESC") 
    @post_months = @posts.group_by { |t| t.posted_at.beginning_of_month } 
end 

vues/archives/indext.html.erb

<div class="archives"> 
    <h2>Blog Archive</h2> 

    <% @post_months.sort.reverse.each do |month, posts| %> 
    <h3><%=h month.strftime("%B %Y") %></h3> 
    <ul> 
     <% for post in posts %> 
     <li><%=h link_to post.title, post_path(post) %></li> 
     <% end %> 
    </ul> 
    <% end %> 
</div> 

Bonne chance et bienvenue à Rails!

+0

Wahhh .. sympa .. merci beaucoup Steve! – Abhi

+0

@steve, Que diriez-vous de cela, cela affecte-t-il la vitesse?si je ne veux pas utiliser ** et juste utiliser cette ligne? Post.all (: sélectionnez => "title, id, posted_at",: order => "posted_at DESC") **. ** @ posts = Post.order ('created_at DESC'). Group_by {| post | post.created_at.beginning_of_month} ** – JAML