紅孔雀 このページをアンテナに追加 RSSフィード

2011-12-18

[][]ハッシュで初期化可能な構造体

Ruby には Struct という構造体を作成するクラスがあります。

例えばユーザ情報(名前とメールアドレス)を保持する構造体を作成する場合は以下のように記述します。

User = Struct.new(:name, :email)

user = User.new('taro', 'taro@example.com')
user.name  # => 'taro'
user.email # => 'taro@example.com'

ところで Rails を使用していると、ハッシュをキーワード引数のように使用するシーンが多々あります。例えばモデルクラスを初期化するときや、メソッドの引数などです。これに慣れてくると、構造体も以下のようにインスタンス化できれば便利だと感じます。

# このように書きたい.
user = User.new(:name => 'taro', :email => 'taro@example.com')

そこで、ハッシュで初期化可能な構造体を考えます。

まずはハッシュで初期化するための initialize メソッドを提供するモジュールを作成します。

module HashInitializable
  def initialize(attributes={})
    attributes.each do |name, value|
      send("#{name}=", value)
    end
  end
end

この HashInitializable を Struct.new で作成した構造体クラスに include すれば、ハッシュで初期化可能な構造体が出来上がります。

User = Struct.new(:name, :email)
User.send(:include, HashInitializable)

user = User.new(:name => 'taro', :email => 'taro@example.com')
user.name  # => 'taro'
user.email # => 'taro@example.com'

HashInitializable は単なるモジュールなので、Struct 以外にも使用可能です。

上記の User を通常のクラスとして以下のように定義することもできます。

class User
  attr_accessor :name, :email
  include HashInitializable
end

user = User.new(:name => 'taro', :email => 'taro@example.com')
user.name  # => 'taro'
user.email # => 'taro@example.com'

それでは最後に、HashInitializable を使用して、ハッシュで初期化可能な構造体を作成します。

class HashInitializableStruct
  def senf.new(*arguments)
    struct = Struct.new(*arguments)
    struct.send(:include, HashInitializable)
    struct
  end
end

これで以下のように記述することができるようになりました。

User = HashInitializableStruct.new(:name, :email)

user = User.new(:name => 'taro', :email => 'taro@example.com')
user.name  # => 'taro'
user.email # => 'taro@example.com'

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

トラックバック - http://d.hatena.ne.jp/benikujyaku/20111218/1324145630