LoginSignup
27
31

More than 5 years have passed since last update.

ハッシュの記法をおさえて、Railsにおける「シンボルは前なの?後ろなの?」問題でもう悩まないんだぞ

Last updated at Posted at 2016-04-20

幾通りもあるハッシュの記法に対して、いつまでたっても常に全力であたふたしっぱなしだったので、ひょいとまとめてみたところ、私的にはエポックメイキングな棚ボタな発見だったので、記録しようと思います。

ハッシュの記法の基本パターン

Rubyでは、次の4つのハッシュの記法が基本パターンです。正式な呼称方法を存じてないので、便宜的に命名しました。

# 文字列型
hash1 = {"title" => "デカルト"}

# 先シンボル型
hash2 = {:title => "ベーコン"}

# 後シンボル型
hash3 = {title: "ニーチェ"}

# 亜シンボル型
hash4 = {title: :カント}

上記の4つの基本パターンをputsすると、次のように返してくれます。

puts hash1
# => {"title"=>"デカルト"}

puts hash2
# => {:title=>"ベーコン"}

puts hash3
# => {:title=>"ニーチェ"}

puts hash4
# => {:title=>:カント}

ハッシュの値を取り出すときは以下のようになります。キーが文字列型である場合と、シンボル型との値の取り出し方の違いに注意します。

puts hash1["title"]
# => デカルト

puts hash2[:title]
# => ベーコン

puts hash3[:title]
# => ニーチェ

puts hash4[:title]
# => カント

Railsにおける記法の振る舞いにも手を広げて考える

ハッシュの基本形のパターンをおさえると、Railsのコーディングにおいても、私にとっては実に悩み深い問題の解消に役立つことがわかりました。そう、「シンボルは前なの?後ろなの?」問題です。

たとえば、ビューにおいてlink_toを使って次のようにclassの指定をするとき、

<%= link_to "ログイン", new_user_session_path, class: "post" %>

第三引数に指定している「class: "post"」は、「"class" => "post"」なの? それとも「:class => "post"」ですか? はたまた「class: :post」ですか?なんていつも悩んでいたのですけども、ハッシュの基本の記法に則った全てのパターンが通ります。だから、「"class" => "post"」と「:class => "post"」と「class: :post」の記法の型へ書き換え可能です。

また、次のようにmethodの指定をする際においても、

<%= link_to "ログアウト", destroy_user_session_path, method: :delete %>

第三引数に指定している「method: :delete」は、「"method" => "delete"」なの? それとも「:method => "delete"」ですか? はたまた「method: "delete"」ですか?なんて感じに書き方をクヨクヨと悩んでいたのですけども、前述の例と同じように全て通ります。

つまり、キーであったり、値に相当するような、二つのコードの組み合わせの指定を記述する際は、厳密にいえばハッシュオブジェクトで無いようなデータを扱うときにおいても、基本のハッシュの記法に則れば問題が起きません。ただし、例外があります。以下にその例を記します。

例外1 routes.rb

ルーティングでは、ハッシュロケットを用いて次のようなハッシュオブジェクトを扱うときと同じようなような記法を用いて記述をします。

  get "products" => "products#index"

調子に乗って、他のハッシュの基本の記法を使っても通るんじゃないの?なんておもったら間違いです。以下のパターンのように書き換えると、いずれにおいてもエラーを吐いてしまいます。

  get :products => "products#index"
  get products: "products#index"
  get products: :products#index

例外2 真偽型、数式型、変数型

true、falseのような真偽型の値や数式を指定する際においても注意が必要です。

<%= form_for current_user do |f| %>
<%= f.text_field :nickname, "maxlength" => 6 %>
<% end %>

上述における「"maxlength" => 6」の数式を指定するような箇所は、「"maxlength" => "6"」や「maxlength: "6"」でも通りますが、ハッシュの記法の基本パターンの四番目に挙げた亜シンボル型の「maxlength: :6」の記述方法ではエラーを吐いてしまいます。

Railsにおける記法の振る舞いをさらに手を広げて考える

次の「before_action :move_to_index」の記述の箇所に注目してください。

before_action :move_to_index, :except => "index"

こんなとき、「before_action move_to_index:」だったかな?「before_action :move_to_index」だったかな?もしくは「before_action "move_to_index"」だったかな?なんて感じに、迷ったりしたことありませんか?これについても簡単です。

組み合わせではなく、何かしらの単一のコードを指定する場合は、「move_to_index:」と「"move_to_index"」が通ると覚えると良いです。というか、「"move_to_index"」も通っちゃうんですね。私的には驚きでしたよ。

他に例を挙げるならば、あるコントローラーにおいてcreateアクション後にnew.html.erbファイルを開くrender指定をするとき、

def create
  Tweet.create(name: "ショーペンハウアー")
  render :new
end

「render :new」なのですか?それとも「render new:」でございますか?えっ、もしかして「render "new"」なの?なんて迷っても、単一のコードを指定する場合は「render new:」を除いた記述はすべて通ると考えると良いです。だから、以下のコードも通ります。

def create
  Tweet.create(name: "ショーペンハウアー")
  render "new"
end

要約

「すっきり美しいルールに落とし込めた!」なんて、一人喜んで書き綴ってみたはいいものの、書いてみるとあっちこっちに考えが飛んで内容がぐちゃぐちゃになってしまいましたので、次のようにまとめます。

単一型
値を指定しない単一型のコードを指定するときは、以下に挙げる文字列型と前シンボル型のみ。シンボルは前なの?後ろなの?ってRailsで迷ったら、before_actionやrenderで登場する単一型の指定は必ずシンボルは前と考えると良い。

"title"

:title

組合せ型
複数のデータを扱う組合せ型は次のようなハッシュの記法に則れば、Railsにおいても大抵は間違いは起きません。

"title" => "デカルト"

:title => "ベーコン"

title: "ニーチェ"

title: :カント

なんて感じに仰々しくまとめてみたのですが、ハッシュを扱うときの実行速度は文字列型よりシンボル型の方が早いなんて話も忘れてはいけませんし、何にしろ試し尽くしていない感が満載なので穴がありそうです。あくまでも参考程度に考えてくださいね。

27
31
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
27
31