概要
プロフィールの編集機能は、ユーザー設定機能として追加する。
プロフィールの画像ファイル名とコメントはユーザー属性として追加した。そこでプロフィール編集に限定しない「ユーザー設定」の機能にこれを含め、今後様々なユーザーの属性設定が可能なようにする。
ユーザー設定の枠組み
editとupdate
ユーザー設定の枠組みにはedit
とupdate
を使う。
編集画面 | 編集処理 | |
URL | /user/:id/edit |
/user/:id/update |
Prefix | edit_user |
update_user |
action | users#edit |
users#update |
method | GET | PATCH |
画面 | edit.html.erb |
edit.html.erb |
ルーティング
枠組みに従ってルーティングを設定。Prefixを使ったユーザーごとのリンクはedit_user_path(:id)
のようになる。
update
アクションへのルーティングのメソッドはpatch
としている。Railsによって、form_with
で扱うモデルがデータベースに未保存の場合はPOST、保存済みの場合はPATCHが送信されるようにHTMLが生成される。
config/routes.rb
1 2 3 4 5 6 7 |
Rails.application.routes.draw do ..... get '/users/:id/edit', to: 'users#edit', as: :edit_user patch '/users/:id/edit', to: 'users#update', as: :update_user end |
コントローラー
枠組みに従ってusers
コントローラーにedit
アクションとupdate
アクションを準備する。
edit
アクションでは、ビューで表示させるためセッション中のユーザーのオブジェクトをインスタンス変数に格納する。
app/controllers/users_controller.rb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
class UsersController < ApplicationController ..... def edit # ビューで表示させるユーザー @user = User.find(user_in_session.id) end def update # update処理 end ..... end |
ビュー
users#edit
でレンダリングされるビューを準備する。
@user.name
を表示させて、受け渡しを確認form_with
とbutton
を配置して、フォームのボタンが押されたときのメソッドを確認
app/views/users/edit.html.erb
1 2 3 4 5 |
<h1><%= @user.name %>さんのユーザー設定</h1> <%= form_with(model: @user, url: update_user_path(user_in_session), local: true) do |f| %> <button>この内容で設定</button> <% end %> |
メニューの追加
ヘッダーメニューにユーザー設定の項目を追加する。
app/views/layouts/application.html.erb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
<!DOCTYPE html> <html> ..... <body> <header> <%= link_to(top_path) do %> <div class="header_logo"></div> <% end %> <h1>EX-BBS</h1> <p><%= user_in_session.name %>さん</p> <ul class="header_menu"> <li><%= link_to("トップ", top_path) %></li> <li><%= link_to("投稿する", "#") %></li> <li><%= link_to("プロフィール", profile_path(user_in_session)) %></li> <li><%= link_to("ユーザー設定", edit_user_path(user_in_session)) %></li> <li><%= link_to("サインアウト", sign_out_path) %></li> </ul> </header> <%= yield %> </body> </html> |
動作確認
ここでヘッダーメニューのユーザー設定をクリックすると、以下の画面が表示され、@user
が渡されているのがわかる。
ここでボタンを押したときの、Railsサーバーのコンソールの表示は以下のとおり。
1 2 3 4 5 6 |
Started PATCH "/users/1/edit" for 10.0.2.2 at 2021-03-28 15:28:34 +0900 Processing by UsersController#update as HTML Parameters: {"utf8"=>"✓", "authenticity_token"=>"eSm3OSQdQEaEChpP7T11URwCT4Ezv/1vWMTGq4/u/JsBm1jnrbJg/agM0p/xY+6YEKPUqx5+9YQUMm3ECZWWCg==", "id"=>"1"} User Load (0.6ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1 No template found for UsersController#update, rendering head :no_content Completed 204 No Content in 34ms (ActiveRecord: 0.6ms) |
PATCHメソッドであることや、URLのパターン、params
の:id
が1にセットされていることがわかる。
留意点
editのルーティングの書き方について
ここではedit
へのルーティングを以下の様に書いた。
1 |
get '/users/:id/edit', to: 'users#edit', as: :edit_user |
この場合、たとえばユーザーIDが1の設定ページのブラウザでのURLは以下の様になる。
http://localhost:3000/users/1/edit
一方、このルーティングを単に以下の様に書いても通る。
1 |
get '/users/edit', to: 'users#edit', as: :edit_user |
このときのURLは次のように形が違うが、ページは適正にレンダリングされる。
http://localhost:3000/users/edit.1
どちらのルーティングの書き方でも、Prefixによるヘルパーは、IDに対応して問題なくルーティングしてくれる。
edit_user_path(:id)
edit/updateのアクションについて
前述のように、モデルのインスタンスがデータベースに登録済みであれば、フォーム実行時のメソッドはRailsによってPATCHとされる。
これをPOSTなどに変更したい場合は、以下の様にform_with
でメソッドを指定し、ルーティングのメソッドもそれに合わせる。
1 |
<%= form_with(model: @user, url: update_user_path(user_in_session), method: post, local: true) do |f| %> |
コントローラーでのIDの指定について
UsersController中、showアクションでユーザープロフィールを表示、edit
アクションとupdate
アクションではプロフィールの変更を行っている。
show
アクションでは、データベースからparams
に格納された:idのユーザーを取得している。
1 2 3 |
def show @user = User.find(params[:id]) end |
一方プロフィールを編集する場合、セッション中のユーザーのID(user_in_session.id
)を使っている。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
def edit @user = User.find(user_in_session.id) end def update @user = User.find(user_in_session.id) if @user.update(user_params) redirect_to profile_path(user_in_session) else flash.now[:danger] = "設定更新できませんでした" flash.now :edit_user, layout: 'application' and return end |
params[:id]
を使うと、他のユーザーのプロフィールにも反応してその内容を見られる。
プロフィールページはサインインしているユーザーのみ見られ、かつ他のユーザーのプロフィールを見られることを想定しているのでこの方法をとる。
一方プロフィールを編集する場合は、サインインしている(セッション中の)ユーザーのデータのみ扱う必要があるので、user_in_session.id
を使う。