読者です 読者をやめる 読者になる 読者になる

kumadori というgemを公開しました。

はじめに

仕事でRubyを使うようになってから5ヶ月程、前々から自分のgemをつくって公開したいと考えていました。

非常に小さい単機能のgemですが、今回はじめて自作gemを作って公開できたのでそのご報告をしたいと思います。

kumadoriとはなにか?

kumadoriRubyでデコレーターパターンをシンプルに実装するためのgemになります。

デコレーターパターンとはプログラミングのデザインパターンのひとつで、既存のオブジェクトにデコレーターオブジェクトをラップすることで柔軟にオブジェクトの機能拡張を行なうことが出来る手法です。

kumadoriという名前ですが、歌舞伎の化粧のことを隈取(くまどり)ということから命名しました。

個人的にソフトウェアの名前に日本語が使われているのが結構好きなので、デコレーターを表すなんか良い感じの日本語ないかな〜って考えた所、 デコレーター -> 装飾者 -> おしゃれする -> 化粧 -> 歌舞伎の化粧を「隈取」という無理な連想ゲームでkumadoriという名前にしました。

使い方

kumadoriはデコレーションの対象となるインスタンスのClass名によって自動的に使用するDecoratorクラスを決定します。

例えばUserクラスのインスタンスをデコレーションするのはUserDecoratorクラス、Animalクラスのインスタンスのデコレーションを行なうのはAnimalDecoratorクラスのような感じになります。 そのため、使用するDecoratorクラスを予めKumadori::BaseDecoratorクラスを継承して定義して下さい。

インスタンスをデコレーションするときはKumadori.decorate(instance)メソッドを使います。

以下に参考コードを記載します。

#
# Basic ruby class.
#
class User
  attr_accesstor :first_name, :last_name

  def initialize(first_name, last_name)
    self.first_name = first_name
    self.last_name  = last_name
  end
end

#
# Decorator class for User instance.
#
class UserDecorator < Kumadori::BaseDecorator
  def full_name
    "#{self.last_name} #{self.first_name}"
  end
end

user = User.new('Yuji', 'Arakaki')

# user instance decorated by UserDecorator
decorated_user = Kumadori.decorate(user)

decorated_user.full_name # => "Arakaki Yuji"

もしデコレーションするインスタンスに該当するDecoratorクラスがない場合、Kumadori::BaseDecoratorクラスによってデコレーションされます。

そのため、もしどのオブジェクトにも共通して追加させたいメソッドなどがあれば、Kumadori::BaseDecoratorクラスをOverrideして定義してください。

class Animal
end

module Kumadori
  class BaseDecorator < ::SimpleDelegator
    def live?
      true
    end
  end
end

animal = Animal.new


# Because of AnimalDecorator class is not defiend,
# it is decorated by Kumadori::BaseDecorator
decorated_animal = Kumadori.decorate(animal)

decorated_animal.live? # => true

配列などのCollection内に入っている各要素をすべてデコレーションしたい場合はKumadori.collection_decorate(collection)を使ってください。

Collection内に入っている要素をすべてデコレーションした新しいCollectionを返します。

members = []
members << User.new('Kanoko', 'Higa')
members << User.new('Ai', 'Kawasaki')
members << User.new('Takeo', 'Kikuchi')

decorated_members = Kumadori.collection_decorate(members)

decorated_members.map{ |user| user.full_name} # => ["Higa Kanoko", "Kawasaki Ai", "Kikuchi Takeo"]

このGemの使いドコロ

僕がこのGemを作ったのは、Railsでモデルに格納されているデータをフォーマットして表示する処理を定義するときに、表示に関する処理はドメインロジックではないのであまりモデル内には記載したくないが記述する良い場所がないのでDecoratorというレイヤーを作りたいと考えたからです。

Decoratorというレイヤーを入れることで、モデル記述していた表示に関するメソッドが整理できるのでより見通しが良くなり、変更もDocoratorを変更すればモデル自体を変更せずに済むのでより柔軟性が高まります。

RailsにDocoratorというレイヤーを導入するGemはactive_decoratordraperという有名どころのgemもあるのですが、どちらもRailsプラグインになっているためRails依存しない形式でデコレーターを簡単に使えるgemにすればすぐに実装出来るしより使いやすいと思ってkumadoriを作ってみました。(まあ、あとで調べるとそういうgemは山ほどあったのですが・・)

おわりに

超絶シンプルなgemですが、人生初のOSSを公開したということでほんの少しテンションが上がっています^^

OSSということでコミットメッセージやREADMEも英語で書いたり、テストどれくらい書けば良いか考えたりして色々楽しかったです。

これからも小さいgemでも大きいWebサービスでも良いので色々開発して定期的にアウトプット出来るように頑張りますd^^