Consernとは何か
モデルやコントローラーの処理において、共通している処理を別ファイルにまとめることでDRYなコードを書くことが出来るものです。
これにより効果的なリファクタリングが可能です!
基本的な使い方
以下のようなモデルがあるとします。
同じ処理をしているので、こういった処理に対してActiveSupport::Concern
を利用してリファクタリングを行う。
...
scope :foo, -> {puts 'foo'}
scope :bar, -> {puts 'bar'}
...
...
scope :foo, -> {puts 'foo'}
scope :bar, -> {puts 'bar'}
...
sample_concern.rbのようなファイルを作成し、共通した処理を記述する。
module Sample
extend ActiveSupport::Concern
included do
scope :foo, -> {puts 'foo'}
scope :bar, -> {puts 'bar'}
end
end
そうすると、先程のuser.rbとpost.rbは以下のように簡単に書けます。
class User < ApplicationRecord
include Sample
...
class Post < ApplicationRecord
include Sample
...
注意点
ビジネスロジックはモデルに書く
コントローラーに定義されたメソッドを、Concernsにしてリファクタリングしようとした際に、このメソッドがビジネスロジックの場合、良くないとされています。
ビジネスロジックがコントローラ、モデルの両方に存在していると、特定の処理を追いかける際に、色んな場所に探しにいく事になるので、コードの見通しが悪くなります。
rubocopのClassLength対策としてConcernsは利用しない
Concernsを利用すると、クラス自体の長さを短くすることが出来て、一見綺麗に見えます。
しかし、rubocopのClassLength警告は「該当クラスが責務を持ちすぎである」ということの指摘なので、実質的な責務を減らさないConcernsは意味がありません。
コードも追いづらくなるので可読性を下げる事になります。
複雑なビジネスロジックをConcernsにする
includeで手軽にメソッドを増やせるのと、コンテキストを分けることで実装をリファクタリングしやすくなる
終わりに
リファクタリングをすることでコードを綺麗にする事が出来るので、良いですよね。
しかし、クラスから単純にConcernsに切り出しても責務が減る事は無いので、責務を減らしたいのであればクラスとして切り出したほうが良いっぽいです。。
最初からConcernsとして切り出そうとするのではなく、まず別の方法も検討してみましょう!