概要
第1段階でユーザーの登録(サインアップ)や認証(サインイン/サインアウト)ができるようになった。これからはサインインしたユーザーに応じた表示や操作を実装していく。
最初に、サインインしているユーザーのプロフィール画像表示を実装する。
ここでは、サインイン中のユーザーがメニューの「プロフィール」をクリックしたときにプロフィールページへ遷移させる。現段階では、サインイン中のユーザー名を表示し、ダミー画像とプレースホルダーのコメントを表示させる。
掲示板の第2段階へ
枠組み
全体の枠組み
全体の枠組み設定は以下のとおりとする。
- プロフィールページのURLは
"ドメイン/profile/ユーザーID"
- アクションは
users#show
(個々のユーザーの情報を表示するためshow
を選択)
- ビューファイルは
app/views/users/show.html.erb
ユーザーに応じた反応
基本の流れは以下の通り。
- ルーティングのURIパターンでユーザーIDを付加
- 遷移ページのリンク先として、ルーティングの名前でサインイン中のユーザーIDを指定
- コントローラーでIDを使ってデータベースからユーザーオブジェクトを取り出す
- ビューにおいて、そのユーザーオブジェクトを使う
実装
ルーティング
まず、プロフィールページへのURLがリクエストされたときのルーティングを設定する。
routes.rb
|
Rails.application.routes.draw do ..... get '/profile/(:id)', to: 'users#show', as: :profile end |
この書き方がユーザーに応じたページへのルーティングの書き方。
- ユーザーを指定するため、データベース中の
users.id
の値をURLで指定
- プロフィールは各ユーザー固有の情報を表示するため、
show
アクション
- Prefixを指定する
:id
を付加した場合、デフォルトのPrefixは設定されないため
指定されたユーザーの取得
ルーティング先のアクションで、:id
を使ってデータベースからユーザーオブジェクトを取り出す。オブジェクトがビューでも使えるよう、インスタンス変数に格納する。
また、サインインしていない状態でshow
アクションを読んだ場合にアクセス制限をかけるよう、before_action
を設定する。ただしサインアップ/サインインに関するアクションはexcept:
で除外しておく。
users_controller.rb
|
class UsersController < ApplicationController before_action :authorize, except: [:sign_up, :sign_in, :sign_up_process, :sign_in_process] ..... def show @user = User.find(params[:id]) end ..... end |
find
はモデルのクラスメソッドで、モデルのIDを指定してデータベースからデータを取得する。引数に指定できるのはIDの値のみ。
ユーザーオブジェクトを使った表示
アクションでセットされたユーザーオブジェクトを使って、ユーザーに応じたページ表示をするためのHTMLを書く。
users/show.html.erb
|
<div class="user_profile"> <h1><%= @user.name %>さんのプロフィール</h1> <div class="contents"> <%= image_tag "https://dummyimage.com/200x200/0b0e4d/23f534.png&text=Profile+Image" %> <p class="comment"> ここにプロフィールコメントを表示 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ </p> </div> </div> |
ここでは@user
のname
を使ってサインイン中のユーザーの名前を表示させている。画像やコメントはダミーだが、サインイン中のユーザーに応じたページが表示されることが確認できる。
なお4行目で、プロフィール画像のプレースホルダーとしてCDNによるダミー画像を利用している。
サインインユーザーによるページの呼び出し
サインイン中のユーザーがメニューの「プロフィール」をクリックしたときに、そのユーザーのプロフィールが表示されるよう、link_to
ヘルパーを設定する。
application.html.erb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
<!DOCTYPE html> <html> ..... <body> <header> <div class="header_logo"></div> <h1>EX-BBS</h1> <p><%= user_in_session.name %>さん</p> <ul class="header_menu"> <li><%= link_to("投稿する", "#") %></li> <li><%= link_to("プロフィール", profile_path(user_in_session)) %></li> <li><%= link_to("サインアウト", sign_out_path) %></li> </ul> </header> <%= yield %> </body> </html> |
ルーティングで設定したPrefixを使ったパス名に(ユーザーID)を指定している。
link_to("...", profile_path(user_in_session))
(user_in_session)
とユーザーオブジェクトそのものを指定しているが、これはRailsでの省略法で、これで(user_in_session.id)
と同じことになる。
パス名ではなく、URIを文字列で指定する方法もある。その場合はルーティングで指定した"/profile/(:id)"
の形になるように文字列で指定する。ただしlink_toだと<%= ... %>
が入れ子にできないためかエラーになるので、a
タグを使うことになる。
<a href="/profile/<%= user_in_session.id %>">プロフィール</a>
スタイル設定
プロフィールページのスタイルを設定する。
users.scss
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
..... // プロフィールページのスタイル .user_profile { h1 { margin: 40px auto; font-size: 20px; text-align: center; font-weight: bold; } .contents { display: flex; margin: 0 auto; width: 600px; .comment { align-self: center; margin-left: 20px; padding: 10px; background-color: #f8f8f8; } } } |
トップページへのリンク
プロフィール画面からトップページに戻るリンクをヘッダーメニューに設定する。application.html.erb
に更に変更を加える。
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
|
<!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("サインアウト", sign_out_path) %></li> </ul> </header> <%= yield %> </body> </html> |
8~10行目は、ヘッダーのロゴにトップページへのリンクをセットしている。他の要素にリンクを設定するには、link_to(...) do
とend
のブロックにする。
14行目では、メニューに「トップ」という項目を追加し、トップページへのリンクを設定している。
表示結果
追補~サイズの固定とスクロール表示
その後、コメント表示を以下の様に変更した。
p
要素の幅と高さを固定
overflow-y: auto
を追加し、コメントが長くなった場合にスクロールバーを表示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
|
// プロフィールページのスタイル .user_profile { h1 { margin: 40px auto; font-size: 20px; text-align: center; font-weight: bold; } .contents { display: flex; margin: 0 auto; width: 600px; .comment { align-self: center; margin-left: 20px; padding: 10px; width: 300px; height: 100px; overflow-y: auto; background-color: #f8f8f8; } } } |