ActiveRecordでgroupしたクエリを集計してviewに表示する


著者(`Author`)毎に記事(`Article`)をグループ化し、  
それを記事一覧に 記事数として表示しようとしています。

`記事一覧`  
|著者ID|著者名|記事数|  
|-----|----------|--------|  
| 1| AAA| 1|  
| 2| BBB| 10|  
| 3| CCC| 5|

`ArticlesController`

[code]

      @articles = Article.all.group(:author_id)
      ~~~ 略 ~~~
      @articles = @aticles.page(params[:page]).per(20))
    
[/code]

`index.html.erb`

[code]

    <% @articles.each do |article| %>
      <tr>
        <td><%= article.author.id %></td>
        <td><%= article.author.name %></td>
        <td><%= article.???????????? %></td>
      </tr>
    <% end %>
    
[/code]

記事のグループ化は出来たのですが、記事数を表示する方法がわかりません。  
`Article.all.group(:author_id).count`のように`.count`を使ってみましたが  
著者IDと記事数のハッシュが返って来てしまうため その後のページネイションがうまく行かなくなります。

また、`.sum`で集計するカラムはスキーマに追加していません ex) `.sum(:amount)`




Railsの機能の[カウンターキャッシュ](http://railsdoc.com/references/counter_cache)を使うと良いと思います。

[code]

    # モデル作成
    $ rails g model Author name articles_count:integer
    $ rails g model Article author:belongs_to
    
    # model
    class Author < ActiveRecord::Base
      has_many :articles
    end
    
    class Article < ActiveRecord::Base
      belongs_to :author, counter_cache: true
    end
    
    # controller
    @authors = Author.includes(:articles).all
    
    # view
    <% @authors.each do |author| %>
      <tr>
        <td><%= author.id %></td>
        <td><%= author.name %></td>
        <td><%= author.articles_count %></td>
      </tr>
    <% end %>
    
[/code]

上のようなカラムを持つ Author を作成すると、articles を追加するたびに articles の count 数が Author
のレコードに保存されます。集約した記事数を検索する場合は、Author の articles_count を検索すれば良いでしょう。

`rails c`での実行結果。Article の INSERT と同時に、Author の UPDATE が行われています。

[code]

    pry(main)> Author.first.articles.create
      Author Load (0.2ms)  SELECT  `authors`.* FROM `authors`  ORDER BY `authors`.`id` ASC LIMIT 1
       (0.2ms)  BEGIN
      SQL (0.3ms)  INSERT INTO `articles` (`author_id`, `created_at`, `updated_at`) VALUES (1, '2015-05-22 21:31:21', '2015-05-22 21:31:21')
      SQL (0.3ms)  UPDATE `authors` SET `articles_count` = COALESCE(`articles_count`, 0) + 1 WHERE `authors`.`id` = 1
       (9.1ms)  COMMIT
    
[/code]




Railsの機能の[カウンターキャッシュ](http://railsdoc.com/references/counter_cache)を使うと良いと思います。

[code]

    # モデル作成
    $ rails g model Author name articles_count:integer
    $ rails g model Article author:belongs_to
    
    # model
    class Author < ActiveRecord::Base
      has_many :articles
    end
    
    class Article < ActiveRecord::Base
      belongs_to :author, counter_cache: true
    end
    
    # controller
    @authors = Author.includes(:articles).all
    
    # view
    <% @authors.each do |author| %>
      <tr>
        <td><%= author.id %></td>
        <td><%= author.name %></td>
        <td><%= author.articles_count %></td>
      </tr>
    <% end %>
    
[/code]

上のようなカラムを持つ Author を作成すると、articles を追加するたびに articles の count 数が Author
のレコードに保存されます。集約した記事数を検索する場合は、Author の articles_count を検索すれば良いでしょう。

`rails c`での実行結果。Article の INSERT と同時に、Author の UPDATE が行われています。

[code]

    pry(main)> Author.first.articles.create
      Author Load (0.2ms)  SELECT  `authors`.* FROM `authors`  ORDER BY `authors`.`id` ASC LIMIT 1
       (0.2ms)  BEGIN
      SQL (0.3ms)  INSERT INTO `articles` (`author_id`, `created_at`, `updated_at`) VALUES (1, '2015-05-22 21:31:21', '2015-05-22 21:31:21')
      SQL (0.3ms)  UPDATE `authors` SET `articles_count` = COALESCE(`articles_count`, 0) + 1 WHERE `authors`.`id` = 1
       (9.1ms)  COMMIT
    
[/code]

