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で対象となるアクションを制御する。

 

Rails – 掲示板 – セッション機能

概要

ユーザー認証によってサインインしたユーザーの情報を保持し、サインアウト時にそれを破棄する。

  • サイトのルートはトップページ
    • サインインしていなければサインインページへリダイレクト
    • サインイン中のユーザーの名前表示
    • メニューからサインアウト可能
  • サインインページ
    • サインイン成功後にトップページに遷移
  • サインアップページ
    • サインアップ成功後にトップページに遷移

掲示板の第1段階へ

ヘルパーの追加

ヘルパーモジュールのインクルード

以降、ユーザーセッションの管理に関するメソッドをUserHelperモジュールに書いていく。

プロジェクト内でそれらを共有するため、applicationコントローラーでモジュールをインクルードする。

app/controllers/application_controller.rb

ヘルパーモジュールのメソッド定義

ユーザーのサインイン/サインアウト処理、サインイン中のユーザーを取得するメソッドを、UserHelperモジュールに書く。

セッション中のユーザーをインスタンス変数に保持する。

app/helpers/user_helper.rb

サインイン・サインアウト処理

サインイン処理

サインインに成功した場合、セッションを開始してユーザIDを登録する。

app/controllers/users_controller.rb

サインアップ後の処理

サインアップが成功した場合も、サインイン状態と同様にセッション登録してトップページに遷移する。

サインアウト処理の追加

サインイン中のユーザーがサインアウトを要求した時のアクションを、usersコントローラーに定義する。

サインアウトにあたってセッションを停止し、サインインページに遷移する。

ルーティングの設定

サインアウトのルーティングを追加する。

ビューの修正・サインアウト

ヘッダー部にサインイン中のユーザー名を表示する。

また、ヘッダーメニューのサインアウトのリンク先をsign_outアクションとする。

 

Rails – フィルター

概要

フィルターは、コントローラーのアクションが実行される前や後などに登録した関数が実行されるよう設定する。

特定のアクションのときだけ実行したり、指定したアクション以外のときに実行させるよう指定できる。

フィルターの種類

before_action

before_action :コールバック

アクションの実行前に、指定したコールバックを実行するよう設定する。

after_action

after_action :コールバック

アクションの実行後に、指定したコールバックを実行するよう設定する。

around_action

around_action :コールバック

アクションの実行中に、指定したコールバックを実行するよう設定する。

コールバック中にアクションの実行をyieldするような場合に使うらしい。

only/except

コールバックを実行するアクションを限定したり(only)、除外したり(except)する。

before_action :コールバック, only: [...], except: [...]

only/exceptの指定は、コールバックのシンボルをカンマで区切って並べる。

[:コールバック1, :コールバック2, ...]