Railsルーティングを学ぶ①
クラスに新しいメソッドを自分で定義するのではなく、7つのメソッドのみ定義した方がスパゲッティコードになりづらいそう。
まだまだルーティングに関して理解が浅いため、今回はルーティングの学習を行っていきたい。
そもそものRailsルーティングの目的
Railsのルーターは受け取ったURLを認識し、適切なコントローラ内アクションやRackアプリケーションに割り当てます。ルーターは、ビューでこれらのパスやURLを直接ハードコードすることを避けるためにパスやURLを生成することもできます。
Railに乗った開発を進めていくために必要。
URLを作成する書き方
「ボタンを押した際に次の画面に値を渡す」ようなアクションを作成したい場合を考える。
例えば下記のようなルーティングがあるとする。
get '/students/:id', to: 'students#show', as: 'student'
そして、アプリケーションのコントローラに以下のコードがあるとする。
@student = Student.find(params[:id])
上記に対応するビューは以下の通り。
<%= link_to 'Student Record', student_path(@student) %>
生成されるHTMLは以下の通り
<a href ="/patient">Patient record</a>
リンクをクリックするときや、ボタンをクリックして次の画面に遷移するときにaタグやbuttonタグがある。
その際に、遷移先を指定できるのが
<%= link_to 'Student Record', student_path(@student) %>
の
student_path(@student)部分になる。
これは、student#showに@studentにある値を渡していることを指している。
(@student)を添えることで、どのidの生徒情報に遷移すればいいのかを指定することができている。
リソースルーティング
毎回getやpostを直接指定してルーティングを作成するのは骨が折れる。railsはその手間をリソースフルなルーティングを使うことで簡単に省いてくれる。
ソースフルなルーティングを宣言することで、コントローラのindex、show、new、edit、create、update、destroyアクションを個別に宣言しなくても1行で宣言が完了できる。便利〜
Railsのリソースフルルーティングでは、(GET、PUTなどの) 各種HTTP動詞 (verb) と、コントローラ内アクションを指すURLが対応付けられます。1つのアクションは、データベース上での特定のCRUD (Create/Read/Update/Delete) 操作に対応付けられるルールになっています。
例えば下記のようなルーティングが定義されているとする。
resources :optimes
そこうすることでアプリケーション内に以下の7つのルーティングが作成され、いずれもFruitesコントローラに対応付けられることになる。
1つに特定できるアクションはidが付く
上記7つのルーティングで、:idがついているパスとそうでないパスがあることに気づく。通常:idがパスは、前のページからparams[:id]で値を受け取っている。つまり、idを指定することができるアクションには:idが付くと言い換えることができる。
id有: show,edit,update,destroy
id無: index,new,create
名前空間
ある画面から次の画面に遷移するとき、名前空間が使われていることがよくある。namespaceと同じような挙動をするのがscopeとmodulemodule似て非なるものなので、以下のようにまとめた。
scope
blog配下にarticlesが入る。PATHに関してはnamespaceと同じ
scope :blog do
resources :articles
end
Controller
article#index
PATH
/blog/articles
namespace
PATH,Controllerの両方ともblogにネストされている。
namespace :blog do
resources :articles
end
Controller
blog/article#index
PATH
/blog/articles
module
Controllerのみがネストされている
**scope** module: :blog do
resources :articles
end
Controller
blog/article#index
PATH
/articles
ネストは浅い方がいい
上記のように、has_manyやbelongs_toで紐づけられたオブジェクト同士はまだ浅いネストの場合、かろうじて読むことができる。だが、子オブジェクトが増えるにつれてネストが深くなっていき、可読性の低いルーティングが出来上がってしまう。
例えば下記のような名前空間ルーティングがあるとする
resources :sports do
resources :soccers do
resources :balls
end
end
このような深いリソースだと、下記のようにみづらいコードが出来上がってしまう。
/sports/1/soccers/2/balls/3
前述したような深いネストを避けるひとつの方法として、コレクション (index/new/createのような、idを持たないアクション) だけを親のスコープの下で生成するという手法がある。
resources :articles do
resources :comments, only: [:index, :new, :create]
end
resources :comments, only: [:show, :edit, :update, :destroy]
これにより、articles/:id/comments/:idのような複雑なネストを回避することができた。
#生成されるパス
#上段
articles/comments/
#下段
comments/:id/
ちなみに:shallowオプションを使うと下記のように簡単な記述にすることができる。
resources :articles do
resources :comments, shallow: true
#shallow: trueにするだけで、idのある無しを振り分けてくれる。
end
DHHはどのようにRailsのコントローラを書くのか | POSTD