Techioz Blog

レール。関連するテーブルの値の合計を含む「count」列を追加します

概要

カテゴリテーブルと問題テーブルがあります。

カテゴリモデル:

has_many :issues

問題モデル:

belongs_to :category

issue_count をコレクションの仮想属性として返すクエリを作成できます。

Category.left_outer_joins(:issues).select('categories.*, COUNT(issues.*) AS issues_count').group('categories.id')

ただし、次のように、カテゴリ テーブルの値として issues_count を格納する実際の列がテーブルに必要です。

id | name | created_at | updated_at | description | tags | issues_count

解決策

:counter_cache オプションを使用できます。

class Issue < ApplicationRecord
  # NOTE: you can also override the default column name
  #       by specifying a custom column name in the counter_cache declaration instead of true
  belongs_to :category, counter_cache: true
end

:counter_cache オプションは、belongs_to 宣言を含むモデルで指定されていますが、実際の列は、関連付けられた (has_many) モデルに追加する必要があります。これにより、category.issues_count フィールドが ActiveRecord によって自動的に更新されます。

このフィールドを追加し、既存のレコードを更新するには、移行を作成する必要もあります。

class AddIssuesCountToCategory < ActiveRecord::Migration[7.1]
  def up
    add_column :categories, :issues_count, :integer, default: 0
    Category.reset_column_information
    Category.all.each do |c|
      Category.update_counters c.id, issues_count: c.issues.length
    end
  end

  def down
    remove_column :categories, :issues_count
  end
end

また、Ryan Bates は、このトピックに関する RailsCasts の優れたエピソードを紹介しています。 #23 カウンターキャッシュ列