はじめに
こんにちは、普段はフロントエンド(ReactやTypeScript)をメインに開発している私ですが、最近バックエンドのRuby(特にRails)を触る機会がありました。
その中で登場した「Mixin(ミックスイン)」という設計パターン。「Reactのmixinと同じ?」と疑問に思った方も多いのではないでしょうか?
今回はフロントエンド視点で、RubyのMixinパターンをやさしく解説していきます!
Mixinってそもそもなに?
Mixin(ミックスイン)とは、あるクラスに共通の機能を“混ぜ込む”ための仕組みです。
JavaScriptで例えると、以下のようなイメージです
const Logger = {
log(message) {
console.log(`[LOG] ${message}`);
}
};
const obj = {
...Logger,
sayHi() {
this.log("Hi!");
}
};
obj.sayHi(); // [LOG] Hi!
この「共通機能(Logger)を別オブジェクトに混ぜる」という発想が Mixin です。
RubyでのMixinパターン
Rubyでは、モジュール (module) を使ってMixinを実現します。
基本の書き方
# 共通機能を定義
module Greetable
def greet
puts "こんにちは!"
end
end
# クラスに混ぜ込む
class User
include Greetable
end
User.new.greet # => こんにちは!
ここで注目すべきは include Greetable の部分。
この一行で、Userクラスのインスタンスが greet メソッドを使えるようになります。これが「Mixinパターン」の本体です。
🤔 include と extend の違い
メソッド | 追加されるメソッドの種類 | 使用例 |
---|---|---|
include |
インスタンスメソッドとして追加 | User.new.greet |
extend |
クラスメソッドとして追加 | User.greet |
module Hi
def greet
puts "やっほー"
end
end
class Friend
extend Hi
end
Friend.greet # => やっほー(クラスメソッド)
Reactのmixinとの違い
観点 | RubyのMixin | ReactのMixin(古い書き方) |
---|---|---|
書き方 | include モジュール名 |
mixins: [MixinObject] |
主に使われていた時代 | 今でも現役(Railsでも使用) | React v14以前の createClass 時代 |
現代での主流 | module + include | Hook、HOC、カスタムHookなど |
多重ミックス | OK(複数モジュール) | 複雑でバグの温床に |
Ruby Mixinのメリットと注意点
メリット
・コードの再利用性が高い
・継承より柔軟(多重ミックスが可能)
・機能単位で切り出しやすい
注意点
・同じ名前のメソッドがあると上書きされる
・Mixinが多くなると「どこから来たメソッドか」が分かりにくい
Railsでよく使う Mixin(ActiveSupport::Concern)
Railsでは ActiveSupport::Concern を使うことで、より綺麗なMixinが書けます。
# app/models/concerns/logger.rb
module Logger
extend ActiveSupport::Concern
included do
before_save :log_save
end
def log_save
puts "保存されました"
end
end
class Article < ApplicationRecord
include Logger
end
まとめ
用語 | 意味 |
---|---|
module | 機能のまとまり(メソッド定義) |
include | モジュールをインスタンスメソッドとして取り込む |
extend | モジュールをクラスメソッドとして取り込む |
Mixin | 上記を使って、クラスに機能を追加するパターン |
おわりに
フロントエンドエンジニアがRubyを触ると、「クラス構造」や「モジュール」の概念に最初は戸惑うかもしれません。でも、ReactやJavaScriptにも似た概念があるので、それらと比較しながら学ぶと理解が早くなります。
Mixinパターンは、Rubyらしさが詰まった再利用の方法。Rails開発でも頻出なので、しっかり理解しておくと便利です!