RailsはRubyを使用しているため、連想配列を記述するときに、Rubyのハッシュを使うことができます。
ハッシュには=>を使ったPHPのような書き方の他に、シンボルを使って文字数を削減した記述方法もあります。
便利な反面、1つの処理で複数の書き方が存在するため、人や解説によって記述が異なり混乱を招くこともあります。
ここでは、ハッシュ(連想配列)の書き方とその省略形を順を追って解説しています。
基本形
一番基本的な形は、ダブルアロー(Rubyではハッシュロケットという)を使った記述です。
obj = { "key1" => "val1" }
objの中のキー名key1の値を呼び出すときは、obj["key1"]
のようにします。
キー名をシンボルにする
Rubyでは、キー名をシンボル(Symbol)で表すことができます。
シンボルとは、名前を表すオブジェクトのことです。:識別子
とすることで、固有の名前をつけることができます。
obj = { :key1 => "val1" }
objの中のキー名key1の値を呼び出すときは、obj[:key1]
のようにします。
ダブルアローを省略する
キー名をシンボルで指定するとき、ダブルアローを省略することができます。
obj = { key1: "val1" }
ダブルコロンの位置が、キー名の冒頭から、末尾に移動している点に注意が必要です。(JSON形式の書き方のようになります)
objの中のキー名key1の値を呼び出すときは、obj[:key1]
のようにします。
値にシンボルを指定する
Ruby及び、Railsにはあらかじめ登録されているシンボルや後から追加したシンボルがあります。
このシンボル自体を値として指定することもできます。
obj = { key: :val }
これは以下と同じです。
obj = { :key => :val}
引数内でカッコを省略する
メソッドの引数にハッシュ(連想配列)を渡す場合に波カッコ { } を省略することができます。
関数名( key1: "val1", key2: "val2" )
これは以下と同じです。
関数名( { key1: "val1", key2: "val2" })
実例
def hash_details(obj)
obj.each do |key, value|
p "key:" + key
p "value:" + value
end
end
hash_details( "key1" => "val1", "key2" => "val2" )
実行結果は、以下のようになります。
"key:key1"
"value:val1"
"key:key2"
"value:val2"
シンボルの特徴
シンボルを使うことで記述をシンプルにすることができます。
また、シンボルは裏側の処理でもメモリ効率がいいものになっています。
文字列とシンボルの違い
Rubyにおいて文字列は同じ値であっても定義する毎に異なるオブジェクトとして扱われます。一方、シンボルは同じシンボル名であれば、同じオブジェクトとして扱われます。
つまり、変数などで文字列を定義する度に新しいオブジェクトが生成されるのに対し、シンボルを使えば一意のオブジェクトしか生成されません。
このためメモリを削減することができます。
オブジェクトのID番号を調べることができる、object_idメソッドを使って確認することができます。
文字列の場合
文字列の場合、以下のように異なる変数名に同じ値を指定しても、そのオブジェクトのIDは異なるものになります。
string1 = "文字列"
string2 = "文字列"
p string1.object_id #60
p string2.object_id #80
シンボルの場合
シンボルの場合、以下のように異なる変数名に同じ値を指定すれば、そのオブジェクトは全く同じものになります。
symbol1 = :symbol
symbol2 = :symbol
p symbol1.object_id #926428
p symbol2.object_id #926428
シンボルと文字列は完全に異なる
上記のオブジェクトIDからもわかるように、シンボルと文字列は完全に異なるものです。
このため、ハッシュ形式で省略形などの記述をしたときに、完全に一致するのは、=> ありなしの省略形のみです。
obj1 = { "key" => "val" }
obj2 = { :key => "val" }
obj3 = { key: "val" }
obj4 = { :key => :val }
obj5 = { key: :val }
p obj1 == obj2
p obj1 == obj3
p obj1 == obj4
p obj1 == obj5
p obj2 == obj3 #true
p obj2 == obj4
p obj2 == obj5
p obj3 == obj4
p obj3 == obj5
p obj4 == obj5 #true
シンボルの一覧を確認する
現在登録されているシンボルの一覧を表示するには、Symbolクラスに対して、all_symbolsメソッドを使います。
Symbol.all_symbols
実行結果は次のようになります。
[:!, :"\"", :"#", :"$", :%, :&, :"'", :"(", :")", :*, :+, :",", :-, :".", :/, :":", :";", :<, :"=", :>, :"?", :"@", :"[", :"\\", :"]", :^, :`, :"{", :|, :"}", :~, :"..", :"...", :+@, :-@, :**, :<=>, :<<, :>>, :<=, :>=, :==, :===, :!=, :=~, :!~, :[], :[]=, :"::", :"&&", :"||", :"&.", :max, :min, :freeze, :nil?, :inspect, :intern, :object_id, :const_missing, :method_missing, :method_added, :singleton_method_added, :method_removed, :singleton_method_removed, :method_undefined, :singleton_method_undefined, :length, :size, :gets, :succ, :each, :proc, :lambda, :send, :__send__, :__attached__, :initialize, :initialize_copy, :initialize_clone, :initialize_dup, :to_int, :to_ary, :to_str, :to_sym, :to_hash, :to_proc, :to_io, :to_a, :to_s, :to_i, :to_f, :to_r, :bt, :bt_locations, :call, :mesg, :exception, :locals, :not, :and, :or, :div, :divmod, :fdiv,,,,,(更に続く)