Rails – 掲示板 – プロフィールコメント編集

概要

ユーザー設定の枠組みに、プロフィールコメントの編集機能を実装する。

掲示板の第2段階へ

ルーティングの確認

ユーザー設定でルーティングは設定済みだが確認しておく。フォームからのデータはPATCHで送られてくる。

ビューの編集

edit.html.erbにコメント入力欄を追加し、スタイル設定のためのdiv要素を加える。

フォームのボタンが押されると、PATCHメソッドでupdate_user_pathにルーティングされる。その際、セッション中のユーザーのIDがparamsに渡される。

app/views/users/edit.html.erb

また、プロフィール画面でコメント表示するようshow.html.erbを変更する。

app/views/users/show.html.erb

コントローラーの編集

editアクション(再掲)

UsersControllereditでセッションユーザーを取得し、ビューで共用できるようインスタンス変数に格納する(ユーザー設定機能で実装済みだが再掲)。

updateアクション

updateでもセッション中のユーザー取得してインスタンス変数に保存する。

そして、フォームで入力されたパラメーターの内容で@user(セッション中のユーザー)の内容を更新する。

現在のフォームから送られてくるのは:comment(と:id)だけなので、この内容で:idで取得済みのユーザーのコメントが更新される。

  • 更新に成功した場合はプロフィールページへ
  • 更新に失敗した場合は再度ユーザー設定画面へ

user_paramsヘルパーの変更

今の設定では、user_paramsの中で取得が許可されている属性にコメントが含まれていない。

そこでフォームから送られてくるコメントのデータを受信可能とするために、user_params:commentpermitに追加する。

スタイルファイル

ユーザー設定ページのスタイルをusers.scssに追記する。

apps/assets/stylesheets/users.scss

実行結果

ボタンを押して内容がセットされると、プロフィールページに遷移して変更が反映される。

 

Rails – 掲示板 – ユーザー設定の枠組み

概要

プロフィールの編集機能は、ユーザー設定機能として追加する。

プロフィールの画像ファイル名とコメントはユーザー属性として追加した。そこでプロフィール編集に限定しない「ユーザー設定」の機能にこれを含め、今後様々なユーザーの属性設定が可能なようにする。

掲示板の第2段階へ

ユーザー設定の枠組み

editとupdate

ユーザー設定の枠組みにはeditupdateを使う。

編集画面 編集処理
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

コントローラー

枠組みに従ってusersコントローラーにeditアクションとupdateアクションを準備する。

editアクションでは、ビューで表示させるためセッション中のユーザーのオブジェクトをインスタンス変数に格納する。

app/controllers/users_controller.rb

ビュー

users#editでレンダリングされるビューを準備する。

  • @user.nameを表示させて、受け渡しを確認
  • form_withbuttonを配置して、フォームのボタンが押されたときのメソッドを確認

app/views/users/edit.html.erb

メニューの追加

ヘッダーメニューにユーザー設定の項目を追加する。

app/views/layouts/application.html.erb

動作確認

ここでヘッダーメニューのユーザー設定をクリックすると、以下の画面が表示され、@userが渡されているのがわかる。

ここでボタンを押したときの、Railsサーバーのコンソールの表示は以下のとおり。

PATCHメソッドであることや、URLのパターン、params:idが1にセットされていることがわかる。

留意点

editのルーティングの書き方について

ここではeditへのルーティングを以下の様に書いた。

この場合、たとえばユーザーIDが1の設定ページのブラウザでのURLは以下の様になる。

http://localhost:3000/users/1/edit

一方、このルーティングを単に以下の様に書いても通る。

このときのURLは次のように形が違うが、ページは適正にレンダリングされる。

http://localhost:3000/users/edit.1

どちらのルーティングの書き方でも、Prefixによるヘルパーは、IDに対応して問題なくルーティングしてくれる。

edit_user_path(:id)

edit/updateのアクションについて

前述のように、モデルのインスタンスがデータベースに登録済みであれば、フォーム実行時のメソッドはRailsによってPATCHとされる。

これをPOSTなどに変更したい場合は、以下の様にform_withでメソッドを指定し、ルーティングのメソッドもそれに合わせる。

コントローラーでのIDの指定について

UsersController中、showアクションでユーザープロフィールを表示、editアクションとupdateアクションではプロフィールの変更を行っている。

showアクションでは、データベースからparamsに格納された:idのユーザーを取得している。

一方プロフィールを編集する場合、セッション中のユーザーのID(user_in_session.id)を使っている。

params[:id]を使うと、他のユーザーのプロフィールにも反応してその内容を見られる。

プロフィールページはサインインしているユーザーのみ見られ、かつ他のユーザーのプロフィールを見られることを想定しているのでこの方法をとる。

一方プロフィールを編集する場合は、サインインしている(セッション中の)ユーザーのデータのみ扱う必要があるので、user_in_session.idを使う。

 

 

Rails – 掲示板 – アイコンの導入

概要

これまでメニューには「投稿」や「サインアウト」といった文字列を表示していたが、ここでこれらをアイコンに変更する。

アイコンはCDNで提供されるものもあり、ここではFont Awesomeを利用する。

読み込みスクリプトの記述

ヘッダーメニューの共通レイアウト、application.html.erbのheadセクションに、Font Awesomeのアイコンを使うためのJavaScriptを読み込むタグを記述する。

app/views/layouts/application.html.erb

アイコンタグの記述

Font Awesomeのアイコンは、iタグのクラスでアイコンの種類を指定して表示させる。アイコンごとのクラス表現を含むタグは、サイトでアイコンを選択するとコピーできる。

また、Railsのlink_toヘルパーでアイコンをクリックしたときのリンク先を指定する場合、以下の様にdoブロックで囲む。

また、ここでは以下の2つを追加している。

  • アイコンのスタイルを設定するクラスを追加
  • マウスオーバー時に表示されるtitleを追加

こうしてヘッダーメニューを変更したのが以下の内容。

スタイルの設定

アイコンタグのクラスにスタイルを適用するため、SCSSファイルを編集する。

アイコンの間に線を引くための&+liブロックを削除し、.iconブロックを追加してサイズ色を設定している。

app/assets/stylesheets/header.css

Rails – 掲示板 – ユーザー属性の追加

概要

ユーザーモデルにプロフィールに使う画像ファイル名とコメントの2つの属性を追加する。

そのために、既にデータが登録されているデータベースのテーブルに、カラムを追加する。

マイグレーションによるカラム追加

データベースにデータが登録されている状態で、データを損なわずにテーブルのカラムを追加する。大まかな流れは以下のとおり。

  1. カラム追加用のマイグレーションファイルを生成する
  2. 追加用マイグレーションファイルの内容を確認する/記述する
  3. マイグレーションを実行する

現在のテーブルをマイグレートした際のマイグレーションファイルの内容は以下のとおり。

db/migrate/20210320060906_create_users.rb

カラム追加用マイグレーションファイルの生成

カラム追加のためのマイグレーションファイルを生成するコマンドは以下のとおり。

rails generate migration AddAnyToTable col:type ...

  • Anyは一般に追加するカラム名を書くが、任意の文字列でよい
  • Tableはカラムを追加するテーブル名
  • col:typeは追加するカラム名と型で複数指定可
    • 指定しなければ空のマイグレーションファイルが生成され、後から追加内容を記述

マイグレーションファイルの記述

コマンド実行の結果、以下のようなマイグレーションファイルが生成される。

20210326083051_add_coumuns_to_users.rb

このファイルのchangeメソッドにカラム追加の命令を記述。

add_column :table, :col, :type

テーブル名、カラム名、型をシンボルで記述する。

マイグレーションの実行

マイグレーションを実行。

マイグレーションの結果、新たにカラムが追加されている。

データが残っていることを確認。追加されたカラムはupdated_atよりも後ろにある。

Ruby – ランダム文字列

概要

予め指定した文字群を使って、任意の長さのランダム文字列を作る。

<手順>

  1. 文字群を文字列として準備
    chars = "ABCDE"
  2. 配列を準備
    array = Array.new(10)
  3. ランダム文字列を生成
    (array.map! {|e| chars[rand(chars.length)]}).join

考え方

ランダム文字列に使う文字群を文字列として準備する。

chars = "ABCDE"

ランダム文字列長と同じ要素数の配列を準備する。

array = Array.new(10)

配列をランダムに選んだ文字で埋める。

array.map! {|e| chars[rand(chars.length)]}

配列を文字列に変換する。

p array.join

実装例

数字と英大文字・小文字を使って20文字のランダム文字列を生成。

 

Ruby – 文字列・配列・範囲オブジェクトの相互変換

概要

1文字単位を対象として、文字列・配列・範囲オブジェクトの相互変換を整理する。

配列→文字列

array.join

文字列→配列

string.chars
string.split("")

範囲オブジェクト

配列への変換

range.to_a

文字列への変換

range.to_a.join

 

Rails – 掲示板 – 仮のプロフィールページ

概要

第1段階でユーザーの登録(サインアップ)や認証(サインイン/サインアウト)ができるようになった。これからはサインインしたユーザーに応じた表示や操作を実装していく。

最初に、サインインしているユーザーのプロフィール画像表示を実装する。

ここでは、サインイン中のユーザーがメニューの「プロフィール」をクリックしたときにプロフィールページへ遷移させる。現段階では、サインイン中のユーザー名を表示し、ダミー画像とプレースホルダーのコメントを表示させる。

掲示板の第2段階へ

枠組み

全体の枠組み

全体の枠組み設定は以下のとおりとする。

  • プロフィールページのURLは"ドメイン/profile/ユーザーID"
  • アクションはusers#show(個々のユーザーの情報を表示するためshowを選択)
  • ビューファイルはapp/views/users/show.html.erb

ユーザーに応じた反応

基本の流れは以下の通り。

  1. ルーティングのURIパターンでユーザーIDを付加
  2. 遷移ページのリンク先として、ルーティングの名前でサインイン中のユーザーIDを指定
  3. コントローラーでIDを使ってデータベースからユーザーオブジェクトを取り出す
  4. ビューにおいて、そのユーザーオブジェクトを使う

実装

ルーティング

まず、プロフィールページへのURLがリクエストされたときのルーティングを設定する。

routes.rb

この書き方がユーザーに応じたページへのルーティングの書き方。

  • ユーザーを指定するため、データベース中のusers.idの値をURLで指定
    • (:id)の括弧がなくても問題なさそう
  • プロフィールは各ユーザー固有の情報を表示するため、showアクション
  • Prefixを指定する
    • :idを付加した場合、デフォルトのPrefixは設定されないため

指定されたユーザーの取得

ルーティング先のアクションで、:idを使ってデータベースからユーザーオブジェクトを取り出す。オブジェクトがビューでも使えるよう、インスタンス変数に格納する。

また、サインインしていない状態でshowアクションを読んだ場合にアクセス制限をかけるよう、before_actionを設定する。ただしサインアップ/サインインに関するアクションはexcept:で除外しておく。

users_controller.rb

findはモデルのクラスメソッドで、モデルのIDを指定してデータベースからデータを取得する。引数に指定できるのはIDの値のみ。

ユーザーオブジェクトを使った表示

アクションでセットされたユーザーオブジェクトを使って、ユーザーに応じたページ表示をするためのHTMLを書く。

users/show.html.erb

ここでは@usernameを使ってサインイン中のユーザーの名前を表示させている。画像やコメントはダミーだが、サインイン中のユーザーに応じたページが表示されることが確認できる。

なお4行目で、プロフィール画像のプレースホルダーとしてCDNによるダミー画像を利用している。

サインインユーザーによるページの呼び出し

サインイン中のユーザーがメニューの「プロフィール」をクリックしたときに、そのユーザーのプロフィールが表示されるよう、link_toヘルパーを設定する。

application.html.erb

ルーティングで設定した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

トップページへのリンク

プロフィール画面からトップページに戻るリンクをヘッダーメニューに設定する。application.html.erbに更に変更を加える。

application.html.erb

8~10行目は、ヘッダーのロゴにトップページへのリンクをセットしている。他の要素にリンクを設定するには、link_to(...) doendのブロックにする。

14行目では、メニューに「トップ」という項目を追加し、トップページへのリンクを設定している。

表示結果

追補~サイズの固定とスクロール表示

その後、コメント表示を以下の様に変更した。

  • p要素の幅と高さを固定
  • overflow-y: autoを追加し、コメントが長くなった場合にスクロールバーを表示

 

Rails – 掲示板 – 第2段階

概要

第1段階でユーザーの取り扱い全般を実装したが、第2段階ではコンテンツの投稿に関する機能を実装していく。

ここでは以下を含む。

  • プロフィールや新規投稿などユーザーに応じたページの表示と操作
  • CDNによるアイコンの導入
  • データベースへのカラムの追加
  • リレーションを持ったテーブル構造の操作
  • 画像のアップロードなどを含む。

掲示板の全体ページへ

要件

画面遷移

サインイン中の画面遷移を対象とする。

  • /top画面で
    • ユーザーの投稿記事(名前、コメント、画面、日付)を表示(上限数付き)
    • メニューの「プロフィール」からユーザーごとの/profile画面へ
    • メニューの「ユーザー設定」からユーザーごとの/edit画面へ
    • メニューの「投稿する」から/post画面へ
  • /profile画面で
    • ユーザーの名前、画像、コメントを表示
    • コメントの投稿と画像のアップロードが可能(いずれか一方でも可)
    • ヘッダーメニューのロゴあるいは「トップ画面」から/top画面へ
  • /edit画面で
    • プロフィール画像、プロフィールコメントを選択・編集
    • ボタンを押してプロフィールの内容を変更し、/profile画面へ遷移
  • /post画面で
    • コメントの投稿と画像のアップロードが可能(いずれか一方でも可)
    • 記事投稿後、ヘッダーメニューのロゴあるいは「トップ画面」から/top画面へ

データベース

テーブル

登録ユーザーテーブル:users

userテーブルは、プロフィールに表示する以下の項目について新たにカラムに追加。

  • プロフィール画像のファイル名
  • コメントテキスト
カラム名 型(SQL) 型(Rails) 内容
id BIGINT(AI) Rails生成
name VARCHAR(255) string ユーザー名
email VARCHAR(255) string メールアドレス
pasword VARCHAR(255) string パスワード
image_file_name VARCHAR(255) string プロフィール画像ファイル名
comment TEXT text プロフィールコメント
created_at DATETIME Rails生成
updated_at DATETIME Rails生成

投稿記事テーブル:posts

postsテーブルは、Railsが設定する項目以外に以下の項目を持つ。

  • 投稿ユーザーのid(users.idを参照)
  • 投稿記事のメッセージを保存する。なお画像のみの投稿も認めるため、commentNULLを許容する。
カラム名 型(SQL) 型(Rails) 内容
id BIGINT(AI) Rails生成
user_id BIGINT references usersテーブルのid
message TEXT text メッセージ本文
created_at DATETIME Rails生成
updated_at DATETIME Rails生成

投稿画像テーブル:post_images

post_imagesテーブルは、Railsが設定する項目以外に以下の項目を持つ。

  • 投稿記事のid(posts.idを参照)
  • 画像ファイルのファイル名
カラム名 型(SQL) 型(Rails) 内容
id BIGINT(AI) Rails生成
post_id BIGINT references postsテーブルのid
file_name VARCHAR(255) string 画像ファイル名
created_at DATETIME Rails生成
updated_at DATETIME Rails生成

リレーション

テーブル間の関係は以下のとおり。

  • userは0以上複数のpostを持つ
  • postは必ず1つのuserに属する
  • postは0以上複数のpost_imageを持つ
  • post_imagesは必ず1つのpostに属する

検討

コントローラーとアクション

/profile/:id -> users#show

  • ユーザーごとのプロフィールを表示する
  • プロフィールの内容はプロフィール画像とコメント

users#edit, users#update

  • ユーザーごとのプロフィールを編集する
  • 編集内容は、画像の登録/差し替え、コメントの記入/変更

posts_controller.rb

  • 投稿記事を取り扱うコントローラー
  • 投稿記事の新規登録、編集、削除
  • 投稿記事は1つのメッセージと0~複数の画像からなる
  • メッセージがあれば画像はなくてもよく、画像があればメッセージは空でもよい

ビュー

users

  • users/profile.html.erb:ユーザーのプロフィールページ
  • users/edit.html.erb:ユーザー設定ページ
  • posts/new.html.erb:新規投稿ページ
  • posts/edit.html.erb:投稿内容編集ページ

スタイルファイル

プロフィールページやユーザー設定ページのスタイル定義を追加。

  • users.css

投稿関係ページのスタイルは以下のファイルに新規に作成

  • posts.css

実装手順

プロフィール

記事投稿

 

Rails – 掲示板 – トップ画面の仮表示

概要

サインアップ(ユーザー登録)サインイン・サインアウト(ユーザー認証)アクセス制御まで実現できたので、トップページを表示したときに登録済みユーザーの情報を表示させるように仮組みする。

掲示板の第1段階へ

コントローラー

pagesコントローラーのtopアクションで、usersテーブルに登録された全ユーザーをオブジェクトとして取り出し、その名前とメールアドレスを一覧として表示させる。

処理概要は以下のとおり。

  • allメソッド:モデルのクラスメソッドで、テーブルの全データをモデルインスタンスの配列として取り出す
  • orderメソッド:SQLのORDER BY句を適用する
    • 引数は1つの文字列として与え、スペースで区切る
    • 1つ目は並べ替えの基準とするカラム
    • 2つ目は並べ替えの順序(asc:昇順・デフォルト、desc:降順)
  • 取り出した結果は、ビューで利用可能なようにインスタンス変数に格納する

ビュー

コントローラーで得られた@usersの要素を取り出し、テーブルとして出力。

表示結果

 

Rails- 掲示板 – アクセス制御

概要

セッション機能を使って、悪性制御を行う。

サインインしていない状態で登録ユーザー用のページ(今回はトップページ)にアクセスした場合、これを表示せずにサインインページにリダイレクトする。

また、サインイン状態でルートにアクセスした場合はトップページを表示する。

掲示板の第1段階へ

セッション中確認機能の追加

以下のメソッドをUserHelpaerモジュールに追加する。

user_in_session?
アクセスしたユーザーがサインイン中かどうか(そのユーザーのセッションが存在するか)判定するメソッド。
authorize
ユーザーがサインイン状態でなければサインインページにリダイレクトするメソッド。コントローラーのフィルターでコールバックとして登録するのに用いる。

アクション実行前の認証

UserHelperで定義したauthorizeメソッドを、トップページを含むpageコントローラーのフィルターで設定する。

ここではpageコントローラーのフィルターとして設定し、コントローラーにはtopアクションが含まれている。

アクセスしたユーザーがサインイン状態であればtopビューがレンダリングされ、サインインしていなければauthorizeの内容に従ってsign_inページに遷移する。

たとえばアクションによって振り分けたい場合はフィルターのonlyexceptで対象となるアクションを制御する。