如何" desc"订购group_by?

时间:2016-07-04 20:56:18

标签: ruby-on-rails ruby

如何order("created_at desc")几个月?

本月内的文章按降序排列,但不是月份本身。

控制器

def archives
  @posts = Post.order("created_at desc")
  @posts_by_months = @posts.group_by { |t| t.created_at.beginning_of_month }
end

查看

<% @posts_by_months.sort.each do |month, posts| %>
  <%= month.strftime('%b') %>
  <% for post in posts %>
    <%= post.title %>
  <% end %>
<% end %>

3 个答案:

答案 0 :(得分:1)

按月份数字排序时,您必须进行一些明确的转换:

在控制器中:

@posts_by_months = @posts.group_by { |t| t.created_at.beginning_of_month }.
  sort_by { |k, _| k.strftime('%-m').to_i }.reverse

@posts_by_months.each { |month, posts| puts month.strftime('%b') } ;
=> Dec
Nov
Oct
Sep
Aug
Jul
Jun
May
Apr
Mar
Feb
Jan

此处k.strftime('%-m')提取月份编号而不填充字符串,to_i将其转换为数字。如果没有转换,sort_by将应用词汇排序,而不是所需要的。

sort_by的结果不是散列而是二维数组。但这不会影响视图代码。

答案 1 :(得分:1)

使用Enumerable#inject http://ruby-doc.org/core-2.3.1/Enumerable.html#method-i-inject

@posts_by_months = @posts_by_months.inject({}) do |h,(k,v)| 
  h[k] = v.sort do |x,y| 
    y.created_at <=> x.created_at
  end
  h
end

例如:

irb(main):054:0> hash = @posts_by_months.inject({}) {|h,(k,v)| h[k] = v.sort {|x,y| y.created_at <=> x.created_at}; h}
#=> […]
irb(main):055:0> pp hash.first.map(&:created_at)
[Wed, 08 Jun 2016 22:26:34 UTC +00:00,
 Wed, 08 Jun 2016 21:49:49 UTC +00:00,
 Wed, 08 Jun 2016 18:30:44 UTC +00:00,
 Wed, 08 Jun 2016 18:25:40 UTC +00:00]

<强>更新

通过控制器为Rails视图工作。

# app/controllers/website_controller.rb

class WebsiteController < ApplicationController
  def test
    @posts = Post.order("created_at desc")
    @posts_by_months = @posts.group_by {|t| t.created_at.beginning_of_month}
    @posts_by_months = @posts_by_months.inject({}) do |h,(k,v)|
      h[k] = v.sort do |x,y|
        y.created_at <=> x.created_at
      end
      h
    end

    render(:layout => false, :template => 'website/test')
  end
end

使用HAML(http://haml.info)模板:

# app/views/website/test.html.haml

- @posts_by_months.sort.each do |month, posts|
  = month.strftime('%b')
  %br
  %ul
    - for post in posts
      %li
        = post.title

Screenshot of "test.html.haml"

答案 2 :(得分:1)

以防您使用PostgreSQL:

@posts = Post.select('extract(month from created_at) as month, posts.*').order('month DESC, created_at DESC').group_by(&:month)

@posts.each do |month, posts|
  puts "This is the month: #{Date::MONTHNAMES[month]}" 
  puts "And this is array of posts: #{posts}"
end