Torihaji's Growth Diary

Little by little, no hurry.

Rails におけるmoduleのincludeとextend と Concern周りについて

そもそもなぜmoduleを使う必要があるのか

Rails module #Ruby - Qiita

(今回触れるのはこのqiitaで言うとメソッドの格納場所として使用するmoduleです)

いくつかの処理において重複しているような処理を抽出し切り出すことによって管理をしやすくするため

またRailsでは他言語で使用されているような多重継承が使えないためそれを実現させるためにも必要。

結論を先に

moduleをincludeすると、include先のクラスおよびmoduleにおいてインスタンスメソッドとして使用が可能になる

またmoduleをextendするとinclude先のクラスおよびmoduleにおいてクラスメソッドとして使用が可能になる。

よくある使い方で`extend ActiveSupport::Concern`を include元のmoduleに記載すると

1つのモジュール内において簡単にインスタンスメソッドとクラスメソッドを定義できて、

呼び出す時も`include そのmodule`とすればok(※ActiveSupport::Concernを使用するメリットとしては他にもありますが最も恩恵が大きいと思うのはこれだと思うので)

試しに

rails cしたら簡単に試せるので。

例えば下記以外にextendでmoduleを呼び出したけど、インスタンスメソッドとしてやってみたらどうなるかとか

またその逆もそうだし。

自分はとりあえずこれやってみてなるほどとなったし、やってみることをおすすめ。

# Railsコンソールを起動
$ rails c

# その場でmoduleを定義して試す
> module Testable
    def hello
      "hello"
    end
  end

# クラスを作ってincludeのケース試す
> class TestInclude
    include Testable
  end

> test = TestInclude.new
> test.hello  # => "hello"

# 別のクラスを作ってextendのケース試す
> class TestExtend
    extend Testable
  end

> TestExtend.hello  # => "hello"

# Concernを使うケースも試せます
> module TestConcern
    extend ActiveSupport::Concern
    
    def instance_hello
      "instance hello"
    end
    
    class_methods do
      def class_hello
        "class hello"
      end
    end
  end

> class TestBoth
    include TestConcern
  end

> TestBoth.class_hello      # クラスメソッド
> TestBoth.new.instance_hello  # インスタンスメソッド

終わりに

よくあるサイトではextend ActiveSupport::Concernを使用する意味が無駄な記述を減らせるみたいな書きっぷりで

よくわからなかったし、じゃあ試しにやってみようとなっても試し方がわからなくて消化不良で終わっていたので

これをやってみて良かったですね。

ちなみに参考例はclaudeに出してもらいました。

また一歩成長です。