RubyでPlugin機構のサンプルを実装してみます。
参考
設計の参考となる情報は以下の記事にまとまっています。
仕様
- 任意のフォーマットに変換したテキストを出力する
- 入力テキストを引数にあたえる
- 適用フォーマットのリストを引数に与える
- 存在しないフォーマッターを指定した場合は何もしない
設計方針
- フォーマットはPlugin化されている
- フォーマットのPluginのファイル名は
formatters/XXXX-formatter.rb
の命名ルールに従うこと - フォーマットのPluginのクラス名は
XXXXFormatter
の命名ルールに従うこと - フォーマットのPluginは
MessageViewer::Formatters::BaseFormatter
を継承すること
Core gem
構成
├── Gemfile ├── Gemfile.lock ├── README.md ├── Rakefile ├── lib │ ├── formatters │ │ ├── base_formatter.rb │ │ ├── plain_formatter.rb │ │ ├── twice_formatter.rb │ │ └── upper_formatter.rb │ ├── formatters.rb │ └── textviewer.rb ├── spec │ ├── spec_helper.rb │ └── textviewer_spec.rb └── textviewer.gemspec
lib/textviewer.rb
エントリーポイント。
MessageViewer::Viewer.run
で文字列出力処理を実行する。
require 'rubygems' module MessageViewer def self.formatters @formatters ||= {} end class Viewer def self.run(text, formatters) load_formatters formatters.map{|e|MessageViewer.formatters[e]} .compact .reduce(text){|a, f|f.display(a)} end private def self.load_formatters ::Gem.find_files('formatters/*_formatter.rb').each { |formatter| require formatter } end end end require 'formatters'
lib/formatters/base_formatter.rb
Formatter Pluginの基底クラス。
継承時に Plugin を MessageViewer に登録する。
module MessageViewer module Formatters class BaseFormatter def self.inherited(child) child.name =~ /^.*Formatters::(?<plugin_name>.*)Formatter$/ key = Regexp.last_match[:plugin_name].downcase.to_sym MessageViewer.formatters[key] = child end end end end
lib/formatters/upper_formatter.rb
文字列を大文字化する組み込み Plugin Formatter。
require "formatters/base_formatter" module MessageViewer module Formatters class UpperFormatter < BaseFormatter def self.display(text) text.upcase end end end end
その他のコード
その他のコードは省略します。
気になる方は
をご確認ください。
Plugin gem
構成
├── Gemfile ├── README.md ├── Rakefile ├── bin │ ├── console │ └── setup ├── lib │ └── formatters │ └── lower_formatter.rb └── textviewer-lower.gemspec
textviewer-lower.gemspec
# 略 spec.add_runtime_dependency 'textviewer' # 略
lib/formatters/lower_formatter.rb
文字列を小文字化する組み込み Plugin Formatter。
require 'textviewer' module MessageViewer module Formatters class LowerFormatter < BaseFormatter def self.display(text) text.downcase end end end end
テスト
- Lower Plugin 追加前
lower をインストールしていないので無視されて、大文字の結果が返却されています
$ gem list textviewer *** LOCAL GEMS *** textviewer (0.0.1)
require 'pp' pp MessageViewer.formatters print MessageViewer::Viewer.run('hOgE', [:plain, :twice, :upper, :lower]) # {:plain=>MessageViewer::Formatters::PlainFormatter, # :twice=>MessageViewer::Formatters::TwiceFormatter, # :upper=>MessageViewer::Formatters::UpperFormatter} # HOGEHOGE
- Lower Plugin 追加後
lower をインストールしているので無視されて、小文字の結果が返却されています
$ cd textviewer-lower $ rake install:local textviewer-lower 0.0.1 built to pkg/textviewer-lower-0.0.1.gem. textviewer-lower (0.0.1) installed. $ gem list textviewer *** LOCAL GEMS *** textviewer (0.0.1) textviewer-lower (0.0.1)
require 'textviewer' require 'pp' require 'rubygems' pp MessageViewer.formatters print MessageViewer::Viewer.run('hOgE', [:plain, :twice, :upper, :lower]) pp MessageViewer.formatters # {:plain=>MessageViewer::Formatters::PlainFormatter, # :twice=>MessageViewer::Formatters::TwiceFormatter, # :upper=>MessageViewer::Formatters::UpperFormatter} # hogehoge{:plain=>MessageViewer::Formatters::PlainFormatter, # :twice=>MessageViewer::Formatters::TwiceFormatter, # :upper=>MessageViewer::Formatters::UpperFormatter, # :lower=>MessageViewer::Formatters::LowerFormatter}