普段何気なく使用しているConcernについて調査してみた。
Concernとは?
Railsにはデフォルトでapp/controllers/concern
とapp/models/coecern
ディレクトリが用意されている。
Concernの用途としては、特定のロジックや機能などをConcernとして分離させ他のコントローラーやモデルでも再利用できるようにする。
使用例
基本はActiveSupport::Concern
をextendしてconcernを作成し、associationやscope,クラスメソッド等も切り離すことができる
module M
extend ActiveSupport::Concern
included do
has_many :posts
scope :disabled, -> { where(disabled: true) }
end
class_methods do
end
end
ActiveSupport::Concern
をextendしない場合は下記のように書く必要があり、少々わかりづらい。
module M
def self.included(base)
base.extend ClassMethods
base.class_eval do
has_many :posts
scope :disabled, -> { where(disabled: true) }
end
end
module ClassMethods
end
end
自分が実務でconcernを使用したときは、複数のFormオブジェクトで共通したattributeやバリデーションを書く必要があったので、concernを利用した。
実装した後に思ったが、concernを用いずに継承を用いても今回の用件は実現できるのはできた、、
自分の中でどちらが良いのかいまだにハッキリとわかっていないのでわかり次第追記します、、
module SpecificService::User
extend ActiveSupport::Concern
include ActiveModel::Model
include ActiveModel::Attributes
included do
attributes :email, :string
validates :email, presence: true
end
end
今回調査したアンチパターン
ビジネスロジックをconcernで共通化するのはアンチパターンに当たるらしい。
具体例
class UserController < ApplicationController
include RecentUser
def index
@users = recent_user
end
end
module RecentUser
def recent_user
User.order(id: :desc).limit(3)
end
end
ビジネスロジックはモデルに寄せるのが基本なので、上記のような場合はUserモデルにビジネスロジックを追加したほうがいい。
参考記事
我々はConcernsとどう向き合うか 株式会社ウィルネット https://blog.willnet.in › entry › 2019/12/02