ハッシュとシンボル

ハッシュとシンボル
--
 ### ハッシュ
ハッシュは基本的には配列と同じですが、整数値以外のインデックス（要素の番号のこと）が使える点と、要素の並び順が保証されない点が配列と異なります。

~~~console
>> user = {}                          # {}は空のハッシュ
=> {}
>> user["first_name"] = "Michael"     # キーが "first_name" で値が "Michael"
=> "Michael"
>> user["last_name"] = "Hartl"        # キーが "last_name" で値が "Hartl"
=> "Hartl"
>> user["first_name"]                 # 要素へのアクセスは配列の場合と似ている
=> "Michael"
>> user                               # ハッシュのリテラル表記
=> {"last_name"=>"Hartl", "first_name"=>"Michael"}
~~~
ハッシュは、キーと値のペアを波カッコで囲んで表記します。キーと値のペアを持たない波カッコの組（`{}`）は空のハッシュです。

ここで重要なのは、ハッシュの波カッコは、ブロックの波カッコとはまったく別物であるという点です（これは確かに紛らわしい点です）。ハッシュは配列と似ていますが、1つの重要な違いとして、ハッシュでは要素の「並び順」が保証されないという点があります 。要素の順序が重要である場合は、配列を使う必要があります。

ハッシュの1要素を角カッコを使って定義する代わりに、次のようにキーと値をハッシュロケットと呼ばれる`=>`によってリテラル表現するほうが簡単です。
~~~console
>> user = { "first_name" => "Michael", "last_name" => "Hartl" }
=> {"last_name"=>"Hartl", "first_name"=>"Michael"}
~~~

### シンボル
ここまではハッシュのキーとして文字列を使っていましたが、Railsでは文字列よりも **シンボル**を使う方が普通です。シンボルは文字列と似ていますが、クォートで囲む代わりにコロンが前に置かれている点が異なります。例えば`:name`はシンボルです。もちろん、余計なことを一切考えずに、シンボルを単なる文字列とみなしても構いません。

ハッシュのキーとしてシンボルを採用する場合、`user` のハッシュは次のように定義できます。
~~~console
>> user = { :name => "Michael Hartl", :email => "michael@example.com" }
=> {:name=>"Michael Hartl", :email=>"michael@example.com"}
>> user[:name]              # :name に対応する値にアクセスする
=> "Michael Hartl"
>> user[:password]          # 未定義のキーに対応する値にアクセスする
=> nil                      # 未定義のハッシュ値は単純にnil
~~~
シンボルとハッシュロケットの組み合わせを、次のようにキーの名前の「前」ではなく「後」にコロンを置き、その後に値が続くように置き換えられます(h2)。
~~~console
>> h1 = { :name => "Michael Hartl", :email => "michael@example.com" }
=> {:name=>"Michael Hartl", :email=>"michael@example.com"}
>> h2 = { name: "Michael Hartl", email: "michael@example.com" }
=> {:name=>"Michael Hartl", :email=>"michael@example.com"}
>> h1 == h2
=> true
~~~
つまり、
`{ :name => "Michael Hartl" }`と`{ name: "Michael Hartl" }`というコードは等価になります。

### ネストされたハッシュ
ハッシュの値にはほぼ何でも使うことができ、他のハッシュを使うことすらできます。
~~~console
>> params = {}        # 'params' というハッシュを定義する ('parameters' の略)。
=> {}
>> params[:user] = { name: "Michael Hartl", email: "mhartl@example.com" }
=> {:name=>"Michael Hartl", :email=>"mhartl@example.com"}
>> params
=> {:user=>{:name=>"Michael Hartl", :email=>"mhartl@example.com"}}
>>  params[:user][:email]
=> "mhartl@example.com"
~~~
Railsでは、このようなハッシュのハッシュ（またはネストされたハッシュ）が大量に使われています。


配列や範囲オブジェクトと同様、ハッシュも`each`メソッドに応答します。例えば、`:success`と`:danger`という2つの状態を持つ `flash` という名前のハッシュについて考えてみましょう。
~~~console
>> flash = { success: "It worked!", danger: "It failed." }
=> {:success=>"It worked!", :danger=>"It failed."}
>> flash.each do |key, value|
?>   puts "Key #{key.inspect} has value #{value.inspect}"
>> end
Key :success has value "It worked!"
Key :danger has value "It failed."
~~~
ここで、配列の`each`メソッドでは、ブロックの変数は1つだけですが、ハッシュの`each`メソッドでは、ブロックの変数は **キー**と **値**の2つになっていることに注意してください。したがって、 ハッシュに対して`each`メソッドを実行すると、ハッシュ内にある「キーと値のペア」ごとに処理を繰り返します。


最後の例として、便利な`inspect`メソッドを紹介します。これは要求されたオブジェクトを表現する文字列を返します。
~~~console
>> puts (1..5).to_a            # 配列を文字列として出力
1
2
3
4
5
>> puts (1..5).to_a.inspect    # 配列のリテラルを出力
[1, 2, 3, 4, 5]
>> puts :name, :name.inspect
name
:name
>> puts "It worked!", "It worked!".inspect
It worked!
"It worked!"
~~~
ところで、オブジェクトを表示するために`inspect`を使うことは非常に多いので、 `p`メソッドというショートカットがあります。
~~~console
>> p :name             # 'puts :name.inspect' と同じ
:name
~~~

省略
---
実は、Ruby では　**メソッド呼び出しの丸カッコは省略しても構いません**。
次の2つのコードは等価です。
 ~~~console
> message1 = "Hello"
> message2 = "Thanx"
> message3 = "oraora!"
> message1.concat(message2, message3)
=> "Hello Thanx oraora!"
~~~
~~~console
> message1 = "Hello"
> message2 = "Thanx"
> message3 = "oraora!"
> message1.concat message2, message3 #カッコを省略してメソッド呼び出しを書く
=> "Hello Thanx oraora!"
~~~

### 複雑なコード

次に、少し難しいコードを理解していきます。
~~~c
 <%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
~~~
ここではRailsの組み込み関数`stylesheet_link_tag`（引数として指定されたソースのスタイルシート リンク タグを返す）を使ってます。しかし、ここで不思議な点がいくつもあります。第一に、丸カッコがありません。しかし、Rubyではメソッド呼び出しの丸カッコは省略しても構わないので次の２つの行は等価です。
~~~c
# メソッド呼び出しの丸カッコは省略可能。
stylesheet_link_tag("application", "data-turbo-track": "reload")
# 上は以下のように書いても同じ
stylesheet_link_tag "application", "data-turbo-track": "reload"
~~~
したがって、次のコードはstylesheet_link_tagメソッドに引数を2個渡して呼んでいることになります。


次に不思議なのが、2つ目の引数はハッシュのようですが、波カッコがない点です。実は、ハッシュがメソッド呼び出しの **最後**の引数である場合は、波カッコを省略できます。次の2つの行は等価です。
~~~c
# 最後の引数がハッシュの場合、波カッコは省略可能。
stylesheet_link_tag("application", { "data-turbo-track": "reload" })
# 上は以下のように書いても同じ
stylesheet_link_tag("application", "data-turbo-track": "reload")
~~~
最初の引数(`data-turbo-track`)は、スタイルシートへのパスを指定する文字列です。上のコードは`<%= ... %>`で囲まれているので、結果はERBによってビューに挿入されます。


参考文献
--
[Ruby on Rails Tutorial](https://railstutorial.jp/)

[Rails API](https://api.rubyonrails.org/classes/ActionView/Helpers/AssetTagHelper.html#method-i-stylesheet_link_tag)