LoginSignup
2
0

More than 1 year has passed since last update.

Concernのアンチパターン

Posted at

普段何気なく使用しているConcernについて調査してみた。

Concernとは?

Railsにはデフォルトでapp/controllers/concernapp/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

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0