Railsのルーティングでいろいろ試した
ルーティングでいろいろ試してみる。
- resources
- resource
- ルーティングのネスト
- namespaceでグループ化
- collectionとmember
- 設定したルーティングがどういったURLになるか確認する
■まずは一般的なresources
Rails.application.routes.draw do resources :companies end
これで生成されるルーティングは以下。
[15] pry(main)> show-routes Prefix Verb URI Pattern Controller#Action companies GET /companies(.:format) companies#index POST /companies(.:format) companies#create new_company GET /companies/new(.:format) companies#new edit_company GET /companies/:id/edit(.:format) companies#edit company GET /companies/:id(.:format) companies#show PATCH /companies/:id(.:format) companies#update PUT /companies/:id(.:format) companies#update DELETE /companies/:id(.:format) companies#destroy
■resource"s"ではなくresource
複数存在するリソースではなく、単一のリソースである場合は、単数系のresourceを使う。
Rails.application.routes.draw do resource :company end
これで生成されるルーティングは以下。
indexが設定されず、パスにidが付与されない点がresourcesと異なる。
[17] pry(main)> show-routes Prefix Verb URI Pattern Controller#Action company POST /company(.:format) companies#create new_company GET /company/new(.:format) companies#new edit_company GET /company/edit(.:format) companies#edit GET /company(.:format) companies#show PATCH /company(.:format) companies#update PUT /company(.:format) companies#update DELETE /company(.:format) companies#destroy
■ルーティングをネストさせる
以下のようにブロックでルーティングを渡すと、ルーティングに階層を作ることができる。
Rails.application.routes.draw do resource :company do resources :departments end end
[18] pry(main)> show-routes Prefix Verb URI Pattern Controller#Action company_departments GET /company/departments(.:format) departments#index POST /company/departments(.:format) departments#create new_company_department GET /company/departments/new(.:format) departments#new edit_company_department GET /company/departments/:id/edit(.:format) departments#edit company_department GET /company/departments/:id(.:format) departments#show PATCH /company/departments/:id(.:format) departments#update PUT /company/departments/:id(.:format) departments#update DELETE /company/departments/:id(.:format) departments#destroy company POST /company(.:format) companies#create new_company GET /company/new(.:format) companies#new edit_company GET /company/edit(.:format) companies#edit GET /company(.:format) companies#show PATCH /company(.:format) companies#update PUT /company(.:format) companies#update DELETE /company(.:format) companies#destroy
さらにdepartmentsの下にemployeesをネストさせるとこうなる。
[19] pry(main)> show-routes Prefix Verb URI Pattern Controller#Action company_department_employees GET /company/departments/:department_id/employees(.:format) employees#index POST /company/departments/:department_id/employees(.:format) employees#create new_company_department_employee GET /company/departments/:department_id/employees/new(.:format) employees#new edit_company_department_employee GET /company/departments/:department_id/employees/:id/edit(.:format) employees#edit company_department_employee GET /company/departments/:department_id/employees/:id(.:format) employees#show PATCH /company/departments/:department_id/employees/:id(.:format) employees#update PUT /company/departments/:department_id/employees/:id(.:format) employees#update DELETE /company/departments/:department_id/employees/:id(.:format) employees#destroy company_departments GET /company/departments(.:format) departments#index POST /company/departments(.:format) departments#create new_company_department GET /company/departments/new(.:format) departments#new edit_company_department GET /company/departments/:id/edit(.:format) departments#edit company_department GET /company/departments/:id(.:format) departments#show PATCH /company/departments/:id(.:format) departments#update PUT /company/departments/:id(.:format) departments#update DELETE /company/departments/:id(.:format) departments#destroy company POST /company(.:format) companies#create new_company GET /company/new(.:format) companies#new edit_company GET /company/edit(.:format) companies#edit GET /company(.:format) companies#show PATCH /company(.:format) companies#update PUT /company(.:format) companies#update DELETE /company(.:format) companies#destroy
■namespaceを使ってグループ化する
namespaceを使うことで、ブロックに渡したルーティングをグループ化することができる。
(moduleオプションを使うことでも、このnamespaceと同じようなことができるみたい。→Railsのルーティングを極める (後編))
Rails.application.routes.draw do namespace :admin do resources :users end end
[20] pry(main)> show-routes Prefix Verb URI Pattern Controller#Action admin_users GET /admin/users(.:format) admin/users#index POST /admin/users(.:format) admin/users#create new_admin_user GET /admin/users/new(.:format) admin/users#new edit_admin_user GET /admin/users/:id/edit(.:format) admin/users#edit admin_user GET /admin/users/:id(.:format) admin/users#show PATCH /admin/users/:id(.:format) admin/users#update PUT /admin/users/:id(.:format) admin/users#update DELETE /admin/users/:id(.:format) admin/users#destroy
■collectionとmember
resoucesで追加されるルーティング(index/create/new/edit/show/update/destroy)以外の
ルーティングを追加したい場合に、collectionかmemberを使う。
Rails.application.routes.draw do resources :users do collection do get :search end member do get :detail end end end
collectionにはパスにidが付与されず、memberにはパスにidが付与される。
個別のリソースにアクションを設定するのか、
リソース全体にアクションを設定するかで使い分ければいいみたい。
[21] pry(main)> show-routes Prefix Verb URI Pattern Controller#Action search_users GET /users/search(.:format) users#search detail_user GET /users/:id/detail(.:format) users#detail users GET /users(.:format) users#index POST /users(.:format) users#create new_user GET /users/new(.:format) users#new edit_user GET /users/:id/edit(.:format) users#edit user GET /users/:id(.:format) users#show PATCH /users/:id(.:format) users#update PUT /users/:id(.:format) users#update DELETE /users/:id(.:format) users#destroy
■実際のURLがどうなるか確認する
設定したルーティングがどういったURLになるのかを確認できる。
[22] pry(main)> app.search_users_path => "/users/search" [23] pry(main)> app.search_users_url => "http://www.example.com/users/search" [24] pry(main)> app.user_path(1) => "/users/1" [25] pry(main)> app.user_url(1) => "http://www.example.com/users/1"
参考にさせていただきました:
techracho.bpsinc.jp
change_columnでmigrateしたらrollbackできなかった
change_columnでmigrateしたあとにrollbackしようとしたらrollbackできなかった…。
そのときのエラーがこれ。
[] be rake db:rollback == 20160915054652 AddTimestampsToMember: reverting ============================ rake aborted! StandardError: An error has occurred, this and all later migrations canceled: ActiveRecord::IrreversibleMigration
???だったが、
この「ActiveRecord::IrreversibleMigration」エラーというのが「不可逆なマイグレーション」、
つまり取り消せないマイグレーションですよ!ということらしい。
いろいろ調べてみたら、
「changeでは特定のメソッドでしかrollbackが利かない」、ということがわかりました。
railsguides.jp
add_column
add_index
add_reference
add_timestamps
add_foreign_key
create_table
create_join_table
drop_table (ブロックを渡す必要あり)
drop_join_table (ブロックを渡す必要あり)
remove_timestamps
rename_column
rename_index
remove_reference
rename_table
上記であれば、rollbackするとどうなるかをActiveRecordが判断してrollbackしてくれるけど、
それ以外だと自分で定義しないといかんということみたいです。
(今回change_columnを使ってるためにrollbackできなかったっぽい)
じゃあ、rollbackするときはこうして!っていうのを書くときどうするかというと、
reversibleメソッドを使う、もしくはupメソッド・downメソッドを書けばいいそう。
今回はup・downで、upメソッドにmigrateしたい処理、
downメソッドにrollbackするときの処理を書いて、無事migrate→rollbackできるようになりました。
参考にさせていただきました:
blog.jnito.com
newとbuildに違いはあるのか
結論から言うと機能的な違いはないようで、buildは「newメソッドのエイリアス」とのこと。
new - リファレンス - - Railsドキュメント
コンソールで試してみたらたしかに違いはなさそう。
[3] pry(main)> company = Company.new(id: 1) => #<Company:0x007fc4d742ff38 id: 1, name: nil, address: nil, phone_number: nil, mail_address: nil, created_at: nil, updated_at: nil> [7] pry(main)> company.departments.new => #<Department:0x007fc4d70c9948 id: nil, name: nil, company_id: 1, deleted_at: nil, created_at: nil, updated_at: nil> [8] pry(main)> company.departments.build => #<Department:0x007fc4d31e0560 id: nil, name: nil, company_id: 1, deleted_at: nil, created_at: nil, updated_at: nil>
ただ、暗黙的な使い分けはあるようで、
モデルの関係が1:nのとき、1のものにはnewを、nのものにはbuildを使うみたい。
(たしかにドキュメントの例でもそうなってる…)
[Rails][ActiveRecord]modelのnewとbuildの違いについて | Coffee Breakにプログラミング備忘録
例えば、Company(会社)とDepartment(部署)で1:nだとしたら、
Company.new
company.departments.build
となる。