クリップにオピニオンカウンターを追加する

その記事にどれくらいのオピニオンが集まっているのかを表示したいと思います。例えばこんなふうにアイコン付きで数字があればなんかカッコいいですよね。

counter_cacheを使ってRailsらしく実装する

counter_cacheとはRailsの持っている集計機能のひとつです。たくさんのコードを書かずに、かんたんに実装できるのがRailsらしい特徴になっています。

具体的に言うと「関連する子モデルレコードの数を集計して、親モデルレコードに集計結果を保存してくれる機能」ということになります。これを少しのコードで実現することができます。

今回の例で言うと、オピニオンが作られるたびにクリップのopinions_count属性のカウントがアップします。

親モデルにカウンター属性を追加

では、実装方法を説明していきます。まず、親モデルにカウンター用の属性を追加します。この時の属性名ですが、

モデル名+s_counter

とするという決まりがあります。今回の場合は、モデル名がOpinionなのでopinions_counter になります。

以下コマンドを実行して下さい。

# ターミナル

$ rails g migration add_opinions_count_to_clip opinions_count:integer
   # => migrationファイルが作成される

次に、作成されたmigrationファイルにdefault: 0と追加します。

# migrationファイルの編集default: 0を追記

add_column :clips, :opinions_count, :integer, default: 0

migrationファイルを編集した後はrails db:migrateを実行して、変更を反映させましょう。

# ターミナル

$ rails db:migrate 

子モデルにcounter_cache: trueを追加

counter_cacheを使うには、親モデルに属性を追加するだけではなく、子モデルにcounter_cache: trueという記述を追加する必要があります。opinion.rbを以下のように編集して下さい。

# opinion.rb

belongs_to :clip, counter_cache: true

これで、counter_cacheが使えるようになりました。

ターミナルで試してみる

では、実際にカウンターが機能しているかターミナルで試してみましょう。コンソールを立ち上げて、以下を参考に試してみて下さい。まずはユーザーとクリップを用意します。

$ rails c

# ユーザーを用意
> user = User.first

# クリップを用意
> clip = Clip.first

クリップの詳細を見ると、opinions_countは0となっているはずです。

> clip #=> .... opinions_count: 0

次にユーザーがそのクリップにオピニオンを作成してみます。

> user.opinions.create(clip: clip, title: "test", body: "test opinion")

クリップの詳細を再度見てみるとopinions_countは1に増えていると思います。

> clip  #=> .... opinions_count: 1

これで、opinions_countの追加はうまくいっていることが確認できました。

課題

クリップに、ユーザークリップカウンターも追加してみましょう。

無料ビデオ講座のお知らせ

Skillhub [スキルハブ]では無料の動画講座を多数公開しています。他校だと数万円するような講座が無料で受講できます。

無料講座一覧を見る

×