以前から気になっていたconcernsディレクトリが何なのか調べてみた。
app/controllers/concerns/
app/models/concerns/

先に結論。共通化に役立つ。必要なController(Modelも)からだけ呼べるので、影響範囲を限定できる。TaskとControllerの共通化が容易になる。

とりあえず書いてみる

app/controllers/concerns/foo.rb を作成

module Foo
  extend ActiveSupport::Concern

  included do
    def bar
      'baz'
    end
  end
end

app/controllers/top_controller.rb にincludeとbarを追加

class TopController < ApplicationController
  include Foo
  def index
    p "bar: #{bar}"
% rails s
-> http://127.0.0.1:3000/

"bar: baz"

考察

複数のControllerでメソッドを共通化したい時の選択肢

1. 継承元のApplicationControllerに移す
 -> 肥大化するのと使わないControllerからも参照可能なのが課題
2. ApplicationControllerの前に継承元のControllerを追加する
 -> 継承が複雑になるのが課題
3. Serviceを導入する
 -> 目的が明確な場合はとても良いけど、Service間での共通化はどうする?
4. Concernを作ってincludeする
 -> 必要なものだけincludeできるのが良さそう!

Taskから呼び出せそう

lib/tasks/user.rake にもincludeとbarを追加

namespace :user do
  desc '削除予定日時を過ぎたユーザーのアカウントを削除'
  task(:destroy, [:dry_run] => :environment) do |_, args|
    include Foo
    p "bar: #{bar}"
% rails user:destroy

"bar: baz"

考察

継承がないTaskでもConcernをincludeするだけで、Controllerのメソッドを呼び出せる。バッチとフロントの処理の共通化が簡単!

Serviceでも可能だが、new(初期化)してから、目的に応じてメソッドを使い分けるので、難しくないけどお手軽でもない。
あと、標準でディレクトリが用意されていないので、使うべきか悩む。

参考

Concernの参考記事

Service導入の参考記事

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です