Hash をよりパワフルにする hashie gem を試す #ruby

## <i class="fa fa-code" style="font-size:1em;"></i> 概要
Hash をよりパワフルにする hashie gem を試します

## <i class="fa fa-cloud-download" style="font-size:1em;"></i> インストール

~~~bash
$ gem install hashie
~~~

## <i class="fa fa-flask" style="font-size:1em;"></i> サンプル
### サンプルコード: Hashie::Mash
Hash の各要素にドットでアクセス可能になる。

~~~ruby
require 'hashie'

hash_tanaka = { name: 'Tanaka', age: 23 }
tanaka = Hashie::Mash.new(hash_tanaka)
puts tanaka
puts tanaka.name
puts tanaka[:name]
puts tanaka.age
puts tanaka[:age]
~~~

* 動作確認

~~~bash
% ruby mash.rb
#<Hashie::Mash age=23 name="Tanaka">
Tanaka
Tanaka
23
23
~~~

### サンプルコード: Coercion
Hash に入力するデータの型を強制できます。

~~~ruby
require 'hashie'

class BaseCoercableHash < Hash
  include Hashie::Extensions::Coercion
  include Hashie::Extensions::MergeInitializer
end

class Person < BaseCoercableHash
  coerce_key :name, String
  coerce_key :age, Integer
end

tanaka = Person.new(name: 'tanaka', age: 34)
puts tanaka
puts tanaka[:name]
puts tanaka[:age]

class Pet < BaseCoercableHash
  coerce_key :name, String
  coerce_key :age, Integer
end

class Person < BaseCoercableHash
  coerce_key :name, String
  coerce_key :age, Integer
  coerce_key :pet, Pet
end

pochi = Pet.new(name: 'pochi', age: 3)
puts pochi[:name]
tanaka = Person.new(name: 'tanaka', age: 34, pet: pochi)
puts tanaka
puts tanaka[:name]
puts tanaka[:age]
puts tanaka[:pet]
missing_pochi = Person.new(name: 'tanaka', age: 34, pet: "hoge")
~~~

* 動作確認

~~~bash
{:name=>"tanaka", :age=>34}
tanaka
34
pochi
{:name=>"tanaka", :age=>34, :pet=>{:name=>"pochi", :age=>3}}
tanaka
34
{:name=>"pochi", :age=>3}

# Pet 型以外を指定したためエラーが発生
/path/to/ruby/gems/2.1.0/gems/hashie-3.4.1/lib/hashie/extensions/coercion.rb:46:in `rescue in set_value_with_coercion': Cannot coerce property :pet from String to Pet: undefined method `each' for "hoge":String (Hashie::CoercionError)
        from /path/to/ruby/gems/2.1.0/gems/hashie-3.4.1/lib/hashie/extensions/coercion.rb:34:in `set_value_with_coercion'
        from /path/to/ruby/gems/2.1.0/gems/hashie-3.4.1/lib/hashie/extensions/merge_initializer.rb:21:in `block in initialize'
        from /path/to/ruby/gems/2.1.0/gems/hashie-3.4.1/lib/hashie/extensions/merge_initializer.rb:20:in `each'
        from /path/to/ruby/gems/2.1.0/gems/hashie-3.4.1/lib/hashie/extensions/merge_initializer.rb:20:in `initialize'
        from coercion.rb:36:in `new'
        from coercion.rb:36:in `<main>'

~~~

### サンプルコード: Coercion( Collection )
Hash に入力するデータの型を強制できます。( Collection の例 )

~~~ruby
require 'hashie'

class BaseCoercableHash < Hash
  include Hashie::Extensions::Coercion
  include Hashie::Extensions::MergeInitializer
end

class Pet < BaseCoercableHash
  coerce_key :name, String
  coerce_key :age, Integer
end

class Person < BaseCoercableHash
  coerce_key :name, String
  coerce_key :age, Integer
  coerce_key :pets, Array[Pet]
end

pochi = Pet.new(name: 'pochi', age: 3)
mike = Pet.new(name: 'mike', age: 2)
puts pochi[:name]
puts mike[:name]
tanaka = Person.new(name: 'tanaka', age: 34, pets: [pochi, mike])
puts tanaka
puts tanaka[:name]
puts tanaka[:age]
puts tanaka[:pet]
missing_pochi = Person.new(name: 'tanaka', age: 34, pets: [pochi, "mike"])
print miss
~~~

* 動作確認

~~~bash
% ruby coercion_collection.rb
pochi
mike
{:name=>"tanaka", :age=>34, :pets=>[{:name=>"pochi", :age=>3}, {:name=>"mike", :age=>2}]}
tanaka
34

/path/to/ruby/gems/2.1.0/gems/hashie-3.4.1/lib/hashie/extensions/coercion.rb:46:in `rescue in set_value_with_coercion': Cannot coerce property :pets from Array to [Pet]: undefined method `each' for "mike":String (Hashie::CoercionError)
        from /path/to/ruby/gems/2.1.0/gems/hashie-3.4.1/lib/hashie/extensions/coercion.rb:34:in `set_value_with_coercion'
        from /path/to/ruby/gems/2.1.0/gems/hashie-3.4.1/lib/hashie/extensions/merge_initializer.rb:21:in `block in initialize'
        from /path/to/ruby/gems/2.1.0/gems/hashie-3.4.1/lib/hashie/extensions/merge_initializer.rb:20:in `each'
        from /path/to/ruby/gems/2.1.0/gems/hashie-3.4.1/lib/hashie/extensions/merge_initializer.rb:20:in `initialize'
        from coercion_collection.rb:28:in `new'
        from coercion_collection.rb:28:in `<main>'
~~~

## <i class="fa fa-arrow-right" style="font-size:1em;"></i> 強制変換
基本的な型については、暗黙の変換メソッドが利用されます。

|Class|Convertion Method|
|:--:|:--:|
| Integer  | `#to_i`  |
| Float    | `#to_f`  |
| Complex  | `#to_c`  |
| Rational | `#to_r`  |
| String   | `#to_s`  |
| Symbol   | `#to_sym`|

## <i class="fa fa-check-circle" style="font-size:1em;"></i> その他
その他の機能については GitHub の README 参照

* <i class="fa fa-external-link" style="font-size:1em;"></i> [hashie GitHub](https://github.com/intridea/hashie)

## :books: 外部資料
* <i class="fa fa-external-link" style="font-size:1em;"></i> [hashie GitHub](https://github.com/intridea/hashie)
* <i class="fa fa-external-link" style="font-size:1em;"></i> [hashie RubyGems](https://rubygems.org/gems/hashie)