2011-12-18
■[Ruby][Ruby on Rails]ハッシュで初期化可能な構造体
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