【Rails入門】同じscopeを書くならActiveSupport::Concernを使おう

Ruby on Rails(以降、Rails)に、ActiveSupport::Concernというモジュールがあることを知っていますか?

ActiveSupport::Concernは、ModelやControllerのコードを分割するときに使えるモジュールです。

複数のModelやControllerで書かなくてはいけなくなった同じコードを、別のモジュールに分割してまとめることもできます。

他方、ActiveSupport::Concernの使いどころがわかりにくかったり、使いすぎると逆にコードがわかりにくくなったりするという問題もあります。

この記事では、分かりやすい例としてActiveSupport::Concernを使ってscopeをまとめる方法を説明します。

ぜひ試してみてください!

scopeとは

scopeって何だっけ?というところから始めましょう。

scopeは、特定のSQL文をメソッド化するための構文です。

Modelに以下のようなコードを追加すると…

以下のような使いかたで、1990/1/1より前に産まれた人を抽出できます。

scopeについては、以下の記事で詳しく説明していますので、ぜひご覧ください。

【Rails入門】scopeの使い方まとめ
更新日 : 2017年7月15日

ActiveSupport::Concernとは

ActiveSupport::Concernは、ModelやControllerのコードを分割するときに使えるモジュールです。

言い方を変えると、ControllerやModelのコードをモジュール化するために使います。

Viewの場合は部分テンプレート(partial)を使って小分けにしますが、ControllerやModelの場合はActiveSupport::Concernを使って小分けにするイメージです。

以下の記事では、Banana Controllerの一部をBananaOneモジュールに切り出す例を紹介しました。

【Rails入門】Controllerでよく使われる機能を紹介!
更新日 : 2018年8月21日

この記事では、もう少し実践的な使いかたを見ていきましょう。

動作を理解するためのWebアプリを作成する

scopeとActiveSupport::Concernの雰囲気をつかんだところで、動作を確認するために、Rails 5.1をインストールしてWebアプリを作りましょう。

(1)Railsをインストールします。

私は、以下の記事を参考に、VirtualBoxで作成した仮想パソコンにインストールしたLinux Mintに、Railsの開発環境を作成しました。

基本的には記事の手順に従って操作しますが、app/samurai/sample1ディレクトリを作成する代わりに、app/samurai/concern-demoディレクトリを作成しました。

Railsを起動して、ブラウザで画面が表示されることを確認したら、いったんRailsを終了してから次に進みます。

初心者でもかんたん!Ruby on Rails の開発環境の構築手順(Mac/Windows 両対応)
更新日 : 2019年8月9日

Linux Mintのインストールについては、以下の記事で詳しく説明しています。

Linux Mint Cinnamonエディションを使ってみよう
更新日 : 2019年5月22日

(2)Gemfileの最終行に以下の内容を追記します。

Hirbについては、以下の記事で詳しく説明していますので、あわせてご覧ください。

【Rails入門】初心者が知っておくべき3つのgem
更新日 : 2019年8月9日

(3)新しい「端末」を起動して、以下のコマンドを1行ずつ順番に入力します。

(4)以下のコードを1行ずつ順番に入力します。

UserテーブルとPostテーブルにデータが入力され、Railsコンソールが終了します。

これで準備ができました。

scopeを使ってみよう

まずは、ActiveSupport::Concernは脇に置いて、scopeを使ってみましょう。

(1)app/models/user.rbを編集します。

変更前:

変更後:

(2)「端末」で、以下のコマンドを入力します。

(3)以下のコードを1行ずつ順番に入力します。

実行結果:

確かに、1990/1/1より前に産まれた人だけが抽出されていますね。

scopeで定義したメソッドは、update_allなどと組み合わせて使えます。

update_allについては、以下の記事で説明していますので、あわせてご覧ください。

【Rails入門】update_allでレコードをサクッと更新する
更新日 : 2018年8月21日

(4)以下のコードを1行ずつ順番に入力します。

実行結果:

1990/1/1より前に産まれた人のchecktrueに変わりました。

(5)以下のコードを入力します。

Railsコンソールが終了します。

birth_beforeは、app/models/user.rb(User Model)に追加したため、別のModel(たとえば、app/models/post.rb)で使用する場合は、あらためてapp/models/post.rbを編集する必要があります。

ActiveSupport::Concernを使ってみよう

ここからは、複数のModelで同じscopeを使いたい場合は、ActiveSupport::Concernを使おうという話をします。

上で説明した誕生日のように、User Model特有のカラムを扱う場合は、app/models/user.rb(User Model)に直接書くことは正しい対応です。

一方、複数のモデルで共通の処理がある場合は、ActiveSupport::Concernを使ってモジュール化するほうが正しい対応でしょう。

ここでは、User ModelにもPost Modelにも存在するcheckを対象にしたscopeを書いてみましょう。

具体的には、checkがtrueのデータだけを表示するscopeを作成します。

(1)app/models/concerns/common_scope.rbを以下の内容で作成します。

(2)app/models/post.rbを編集します。

変更前:

変更後:

(3)app/models/user.rbを編集します。

変更前:

変更後:

(4)「端末」で、以下のコマンドを入力します。

(5)以下のコード1行ずつ順番に入力します。

実行結果:

app/models/concerns/common_scope.rbで定義したscopeが使えていますね。

Post Modelにもcheck(true)が使えるか確認するために、まずはPost Modelの全レコードを確認します。

(6)以下のコードを入力します。

実行結果:

checkを見ると、trueのレコードとfalseのレコードがありますね。

さて、check(true)が使えるでしょうか。

(7)以下のコードを入力します。

実行結果:

確かにPost Modelに対してもscopeが使えています。

まとめ

今回は、scopeの使いかたをおさらいしてから、ActiveSupport::Concernの使いかたを紹介しました。

ActiveSupport::Concernを使うと、ControllerやModelを小分けにできることも説明しました。

この記事では、複数のModelで共通のscopeを定義しましたが、ControllerでもActiveSupport::Concernを使えますので、ぜひ挑戦してみてください!

ただ、ModelでもControllerでも、小分けにすることで、どこで何が定義されているのか分かりにくくなってしまうという問題もあります。

特に複数人で開発しているときには、無闇に小分けにして開発効率が落ちないように注意しましょう。

いろいろなパターンで試してみて、ちょうどよい方法を見つけてください!

LINEで送る
Pocket

最短でエンジニアを目指すなら侍エンジニア塾

cta_under_bnr

侍エンジニア塾は業界で初めてマンツーマンレッスンを始めたプログラミングスクールです。これまでの指導実績は16,000名を超え、未経験から数多くのエンジニアを輩出しています。

あなたの目的に合わせてカリキュラムを作成し、現役エンジニア講師が専属であなたの学習をサポートするため効率よく学習を進めることができますよ。

無理な勧誘などは一切ありません。まずは無料体験レッスンを受講ください。

無料体験レッスンの詳細はこちら

書いた人

侍テック編集部

侍テック編集部

おすすめコンテンツ

あなたにぴったりなプログラミング学習プランを無料で診断!

プログラミング学習の効率を劇的に上げる学習メソッドを解説