Tbpgr Blog

Employee Experience Engineer tbpgr(てぃーびー) のブログ

Ruby | ユーザーが拡張可能なライブラリを作成する

概要

ユーザーが拡張可能なライブラリを作成する

詳細

ユーザーが拡張可能なライブラリを作成します。
※ライブラリ作成者側の視点の話

ライブラリの特定の処理に、色んなパターンがあったとします。
例えばhtmlのタグを出力する機能なら、div/span/body・・・・など。
ここで、ライブラリ側がdiv/spanしか用意しておらず、
ユーザーがpタグを利用したい場合に、拡張可能な形式にしておくと便利です。

Rubyはダックタイピングなので、特定のメソッドがあることのみ想定しておけばよいです。
後はそのメソッドを実装したクラスをユーザーにどのように指定させるかを決めます。
色々と方法はあると思いますが、今回はDSLの設定ファイルにクラスを設定させます。

サンプルコード

仕様

ライブラリで、特定のメソッドを持つクラスを想定して処理を記述します。
今回の例ではDSL用に用意したhogeableメソッドhogeメソッドを実装したクラスを
渡すとユーザー定義のクラスをライブラリ側で実行します。

構成

extensible_library.rb:ライブラリ
calee.rb:ライブラリが読み込むDSLで記述されたファイル(Gemfileなどのような立ち位置)
extended_class1.rb:ユーザーが拡張するクラス1
extended_class2.rb:ユーザーが拡張するクラス2

extensible_library.rb
# encoding: utf-8

class HogeExecutor
  # DSLで記載されたファイルをパースして実行
  def execute
    src = File.open("calee.rb") {|f|f.read}
    instance_eval src
  end

  # hogeableに指定されたクラスがhogeメソッドを実装していることを前提に処理するDSL用メソッド
  def hogeable(klass)
    p klass.new.hoge
  end
end

class Hage
  def hoge
    "hage"
  end
end

HogeExecutor.new.execute
calee.rb
# encoding: utf-8
require "./extended_class1"
require "./extended_class2"

# ユーザー定義クラス1をDSLに指定する
hogeable Hoge
# ユーザー定義クラス2をDSLに指定する
hogeable Hige
# ライブラリが用意しているクラスを利用する
hogeable Hage
extended_class1.rb
# encoding: utf-8

# ユーザー側が追加したクラス
class Hoge
  def hoge
    "hoge"
  end
end
extended_class2.rb
# encoding: utf-8

# ユーザー側が追加したクラス
class Hige
  def hoge
    "hige"
  end
end

出力

extensible_library.rbを実行

"hoge"
"hige"
"hage"