OpenStructを使うと、Hashから簡単にオブジェクトを作ることができます。
Hashのキーでアクセスする代わりに、OpenStructではメソッドを使って値にアクセスしたり、値を設定したりできます。
attributes = { name: "Jeremy Walker", age: 21, location: "Nomadic" }
person = OpenStruct.new(attributes)
person.name
#=> Jeremy Walker
person.location
#=> Nomadic
# Update the age
person.age = 35
# It sets correctly
person.age
#=> 35
この方法のうれしい点は、ブロック構文を使うときにショートカットを利用できることです。
ブロックがメソッドを1つだけ呼び出す場合は、そのブロックを&:とメソッド名に置き換えられます。
たとえば、次の2行は同じ意味です。
people.sum { |person| person.age }
people.sum(&:age)
これまでの演習で見てきたクラスはすべて、Rubyのコアライブラリに含まれていました。
OpenStructはRubyの標準ライブラリ(しばしば「stdlib」と略されます)の一部です。標準ライブラリは、日付やjson、ネットワークなどを扱うためのクラスを集めたものです。 また、コードを扱いやすくするための便利な機能も提供しています。
コアライブラリ以外のクラス(別のファイルに書いた自分のコード、標準ライブラリのクラス、外部の依存関係など)を使うときは、使う前にrequireメソッドで読み込む必要があります。
たとえば、次のようになります。
require 'ostruct'
person = OpenStruct.new(name: "Jeremy Walker")
# ...
以前に作った在庫管理システムの作業を続けていきます。OpenStructとブロックの省略記法を知ったので、コードを少しリファクタリングすることにしました。アイテムをハッシュとして保存する代わりに、新たに身につけた知識を活かしていきます。
在庫にあるアイテムのリストはこれまでどおり取得できるようにしたいところですが、今回はメソッドを呼び出せるオブジェクトとして扱えるようにします。
inventory = BoutiqueInventory.new([
{price: 65.00, name: "Maxi Brown Dress", quantity_by_size: {s: 3, m: 7, l: 8, xl: 4}},
{price: 50.00, name: "Red Short Skirt", quantity_by_size: {}},
{price: 29.99, name: "Black Short Skirt", quantity_by_size: {s: 1, xl: 4}},
{price: 20.00, name: "Bamboo Socks Cats", quantity_by_size: {s: 7, m: 2}}
])
inventory.items.first.name
# => "Maxi Brown Dress"
inventory.items.first.price
# => 65
inventory.items.size
# => 4
item_namesをリファクタリングするitem_namesを、ハッシュではなく新しく学んだブロックの省略記法を使うようにリファクタリングします。念のため、このメソッドは次の値を返す必要があります。
BoutiqueInventory.new([
{price: 65.00, name: "Maxi Brown Dress", quantity_by_size: {s: 3, m: 7, l: 8, xl: 4}},
{price: 50.00, name: "Red Short Skirt", quantity_by_size: {}},
{price: 29.99, name: "Black Short Skirt", quantity_by_size: {s: 1, xl: 4}},
{price: 20.00, name: "Bamboo Socks Cats", quantity_by_size: {s: 7, m: 2}}
]).item_names
# => ["Bamboo Socks Cats", "Black Short Skirt", "Maxi Brown Dress", "Red Short Skirt"]
total_stockをリファクタリングするtotal_stockを、ハッシュを参照するのではなく、OpenStructのメソッドを使うようにリファクタリングします。念のため、このメソッドは次の値を返す必要があります。
BoutiqueInventory.new([
{price: 65.00, name: "Maxi Brown Dress", quantity_by_size: {s: 3, m: 7, l: 8, xl: 4}},
{price: 50.00, name: "Red Short Skirt", quantity_by_size: {}},
{price: 29.99, name: "Black Short Skirt", quantity_by_size: {s: 1, xl: 4}},
{price: 20.00, name: "Bamboo Socks Cats", quantity_by_size: {s: 7, m: 2}}
]).total_stock
# => 36