hiyoko-programingの日記

プログラミングを勉強したてのひよっ子。   エンジニア目指して勉強中。

映画レビューサイトのコード その3

STEP5:Active Storageを使って画像のアップロード機能をつける

せっかくユーザーの概念を作ったのでユーザーのアイコンを設定できるようにしたい。

そこで画像アップロード用のgemであるActive Storageを使って、画像のアップロード機能を実装する。Active Storageを使うと非常に簡単に画像のアップロード機能を実装することができる。

 作業内容

1.画像変換ツールをインストール
2.Active Storageをインストール
3.userモデルにActive Storageの設定を追記

必要なツールをインストール

Active Storageで画像を加工してから(サイズや色など)アップロードするには別のツールをインストールする必要がある。

ImageMagickという画像変換ツールと、それをRailsから使うためのmini_magickというgemをインストールする。

 ImageMagick

ImageMagickは、コマンドラインから簡単に画像の保存形式の変更などが行えるツール。

ターミナル
1
$ brew install imagemagick

ImageMagickがインストールできたら、mini_magickをインストールします。gemfileに追記する。

gemfile
1
gem 'mini_magick'
ターミナル
1
$ bundle install

gemを新しくインストールしたのでサーバーを再起動。

ターミナル
1
2
3
4
5
6
# サーバーの立ち上がっているターミナルの画面に移動して
# サーバーの停止コマンド「control + c」
#####
# サーバーの停止
#####
$ rails s 

Active Storageのインストールを行う

Active Storageを使う準備を行う。

ターミナル
1
2
$ rails active_storage:install
$ bundle exec rake db:migrate

rails active_storage:installコマンドを実行すると、Active Storageが使用するテーブル用のマイグレーションファイルが作成される。続けてマイグレートを行う。

これでActive Storageの導入は完了。

 

要点チェック

 

Userモデルに設定を追加

ユーザーモデルにActive Storage用の設定を追加する。

user.rb
1
2
3
4
5
6
7
8
class User < ApplicationRecord
  #Include default devise modules. Others available are:
  #:confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable

  has_one_attached :avatar
end

この記述を追加することで、ユーザーのレコードと画像を紐づけることができる。ユーザーテーブルにカラムを追加する必要はない。

STEP6:ユーザー登録機能の充実

Active Storageによってユーザーのアイコン画像のアップロードが可能となったのでサインアップ画面でアイコン画像の設定をするビューをつくる。さらにユーザーのニックネームもサインアップ画面で設定できるようにする。

 作業内容

1.usersテーブルにニックネームカラムを追加する
2.ビューを追加する
3.ストロングパラメーターを追加する
4.バリデーションを設定する

1.usersテーブルにニックネームカラムを追加

ニックネームのカラムがまだUsersテーブルになかったので、マイグレーションファイルを生成してニックネーム用のカラムnicknameを追加する。

 問題5:usersテーブルにnicknameカラムを追加する

ヒント①:rails g migrationコマンドを使う
ヒント②:Sequel Proでカラムが作成されたか確認する

2.ビューを追加

サインアップ画面にニックネームを入力するフォームとアイコン画像をアップロードできるフォームを作る。完成すると、以下のようになる。

サインアップ画面
https://tech-master.s3.amazonaws.com/uploads/curriculums//c1daad88b78b4f5d64659534b063f1ea.png

サインアップ画面はRailsform_forメソッドを使って記述されている。
ニックネームはテキストフィールド、アイコン画像にはファイルフィールドと呼ばれるファイルのアップロード用のフィールドを生成する。
テキストフィールドはtext_field、ファイルフィールドはfile_fieldのフォームタグを利用することで生成できる。また、カラム名の指定も忘れずに行う。

  • テキストフィールドの生成
1
  <%= f.text_field :カラム名 %>
  • ファイルフィールドの生成
1
  <%= f.file_field :カラム名 %>
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<div class="bgcolor-white pt1em pb1em" id="contents">  <div id="main_cnt_wrapper">
  <div id="yjContentsBody">
    <div class="yjContainer">
      <div class="form_box">
        <h2>mooovi<span>新規登録</span></h2>

        <%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
          <%= devise_error_messages! %>

          <div class="label"><%= f.label :email %><br />
          <%= f.email_field :email, autofocus: true, :placeholder => 'メールアドレスを入力' %></div>

          <div class="label"><%= f.label :password %> <% if @validatable %><i>(<%= @minimum_password_length %> characters minimum)</i><% end %><br />
          <%= f.password_field :password, autocomplete: "off", :placeholder => 'パスワードを入力' %></div>

          <div class="label"><%= f.label :password_confirmation %><br />
          <%= f.password_field :password_confirmation, autocomplete: "off", :placeholder => 'パスワードを入力(確認)' %></div>

          <div class="label"><%= f.label :nickname %><br />
          <%= f.text_field :nickname %></div>
          <div class="field">
          <%= f.file_field :avatar %>
          </div>

          <div class="submit">
          <div class="actions">
          <%= f.submit %>
          </div></div>

          <div class="more_link_box">
          <strong>すでにアカウントを持っていますか?</strong>
          <%= render "devise/shared/links" %>
          </div>
        <% end %>
      </div>
    </div>
  </div>
</div>

 

3.ストロングパラメーターを追加

今のままニックネームを入力とアイコン画像をアップロードしてユーザーの作成ボタンを押すと、nicknameとimageが設定されない。これはdeviseで設定されているstrong_parametersによってnicknameとimageのパラメーターが許可されていないため。

そこで、deviseのstrong_parametersに新しく許可するパラメーターを追加する必要がある。deviseではそのためのメソッドdevise_parameter_sanitizerが用意されている。

 devise_parameter_sanitizer

devise_parameter_sanitizerメソッドを使うとdeviseで設定されているstrong_parametersに対してパラメーターを追加することができる。具体的な使い方は以下です。

【例】

1
  devise_parameter_sanitizer.permit(追加したいメソッドの種類, keys: [追加したいパラメーター名])

devise_parameter_sanitizerメソッドで指定する引数は2種類ある。

1つ目が「StrongParametersを追加したい処理の種類」。

引数の値 処理
:sign_up 新規登録時
:sign_in ログイン時
:account_update レコードの更新時

 

新規登録時にStrongParametersを追加したい場合は1つ目の引数に:sign_up、ログイン時なら:sign_in、レコードの更新時には:account_updateを渡す。

2つ目の引数には追加したいパラメーター名を渡す。複数のパラメーターを送る場合は,(カンマ)区切りで渡す。

1
  devise_parameter_sanitizer.permit(追加したいメソッドの種類, keys: [:パラメーター1, :パラメーター2,..])

例えば、レコードの更新時nameageというパラメーターをstrong_parametersに追加したいとすると以下のように書ける。

1
devise_parameter_sanitizer.permit(:account_update, keys: [:name, :age])

まず、一番目の引数に:account_updateを指定している。これはレコードの更新時のstrong_parametersに新しくパラメーターを追加するという意味。
二番目の引数には:name:ageを指定する。これで、nameとageという2つのパラメーターを追加できるようになる。

これを利用して、nicknameimageのパラメーターをサインアップのアクションのときにstrong_parametersに追加する。

 

また、devise_parameter_sanitizerメソッドはbefore_actionに設定する。これはdeviseの処理であるので、記述するのはDeviseのコントローラを継承したコントローラか、もしくはApplicationController。
しかし今回Deviseのコントローラを継承したコントローラは作成していないのでApplicationControllerに記述する。

application_controller.rb
1
  before_action :メソッド名

ここで、devise_parameter_sanitizerメソッドを直接before_actionに記述してはいけない。devise_parameter_sanitizerを呼び出すためのメソッドを作成してそのメソッドを呼び出すようにする。

application_controller.rb
1
2
3
4
5
  before_action :configure_permitted_parameters

  def configure_permitted_parameters
    # devise_parameter_sanitizerメソッドを呼び出す
  end

さらにこのままではエラーが起きてしまう。すべてのコントローラがApplicationControllerを継承している。すなわち、この記述ではすべてのコントローラのアクションの前で

devise_parameter_sanitizerメソッドが呼び出される。
実は、devise_parameter_sanitizerメソッドはdeviseで追加されたメソッドなので、Deviseのコントローラ以外で呼び出すことができない。よって、before_actionを適応するコントローラを指定する。

before_actionではifというオプションを指定することができる。これはbefore_actionを呼び出す条件を指定するもので、今回はコントローラの種類を指定するので以下のように書く。

application_controller.rb
1
  before_action :メソッド名, if: :コントローラ名?

 問題6:user登録時のストロングパラメーターを追加する

作業ファイル:app/controllers/application_controller.rb
ヒント①:サインアップ時に、nicknameとimageというキーを許可するよう、追記。
ヒント②:deviseのコントローラにあるアクションが動いた時のみ、before_actionが動くよう書く。
【例】
app/controllers/application_controller.rb
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
class ApplicationController < ApplicationRecord

  # Prevent CSRF attacks by raising an exception.
  # For APIs, you may want to use :null_session instead.
  deviseコントローラのアクションが動いた時のみ、configure_permitted_parametersを動かす処理を書く
  protect_from_forgery with: :exception

  def configure_permitted_parameters
    devise_parameter_sanitizer.permit(ストロングパラメーターを追加するアクション, keys: [追加したいキー])
  end
 
end

実際に、ユーザーのニックネームと画像を設定して

新規登録画面でニックネームとアバター画像を含む、すべての情報を入力して登録する。

https://tech-master.s3.amazonaws.com/uploads/curriculums//25e61c3ace9dbc91669185b15c7d2964.png

新規登録したら、Sequal proでusersの情報を確認。

https://tech-master.s3.amazonaws.com/uploads/curriculums//f36facff225623c5f0c160c690b3a0a2.png

  

要点チェック

 

4.バリデーションを設定

現在の状態ではパスワードとIDさえ入力していればサインアップできる。しかしニックネームも必須の入力項目にしたい。そこでニックネームが入力されていなければエラーを返すようにバリデーションを設定する。

さらにニックネームが必須項目であることを知らせるために以下のようにテキストフィールドにプレイスホルダーを設定する。

 validation(検証)

validationとは、入力フォームを通じてビューからサーバー側へパラメーターが送られてきた際、正常な値か検証することができる機能。

 validates :カラム名, presence: true

フォームの中身があるかないかを検出し、無い場合は保存を実行しない。

例えば、userのemailを入力必須にしたい場合、以下のように書くことができる。

user.rb
1
2
class User < ApplicationRecord
    validates :email, presence: true

この状態でユーザーの新規登録時にemailを入力しなかった場合、以下のようなエラーが表示され、userを登録することができなくなる。

ニックネームを入力しなかった場合

バリデーション

 placeholder: ''

フォームの中に、''で囲んだ文字をフォームの値が空の時に薄く表示しておくことができる。userが何を入力すれば良いかわかりやすくするためである。text_fieldメソッドのオプションとして、以下のように利用する。

sample.html.erb
1
  <%= f.text_field :nickname, placeholder: 'ニックネームを入力(必須)' %>

すると、ブラウザ上では以下のように表示される。

プレイスホルダーの設定

バリデーションとプレースホルダーを実装。

app/models/user.rb
1
2
class User < ApplicationRecord
    validates :nickname, presence: true
app/views/devise/registrations/new.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
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<div class="bgcolor-white pt1em pb1em" id="contents">
  <div id="main_cnt_wrapper">
    <div id="yjContentsBody">
      <div class="yjContainer">
        <div class="form_box">
          <h2>mooovi<span>新規登録</span></h2>
          <%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
            <%= devise_error_messages! %>

            <div class="label"><%= f.label :email %><br />
            <%= f.email_field :email, autofocus: true, placeholder: 'メールアドレスを入力' %></div>

            <div class="label"><%= f.label :password %> <% if @validatable %><i>(<%= @minimum_password_length %> characters minimum)</i><% end %><br />
              <%= f.password_field :password, autocomplete: "off", placeholder: 'パスワードを入力' %></div>

            <div class="label"><%= f.label :password_confirmation %><br />
              <%= f.password_field :password_confirmation, autocomplete: "off", placeholder: 'パスワードを入力(確認)' %></div>

            <div class="label"><%= f.label :nickname %><br />
            <%= f.text_field :nickname, placeholder: 'ニックネームを入力(必須)' %></div>
            <div class="field">
            <%= f.file_field :avatar %>
            </div>

            <div class="submit">
              <div class="actions">
                  <%= f.submit %>
              </div>
            </div>
            <div class="more_link_box">
              <strong>すでにアカウントを持っていますか?</strong>
              <%= render "devise/shared/links" %>
            </div>
          <% end %>
        </div>
      </div>
    </div>
  </div>
</div>

実装できたら、実際にプレースホルダーが表示される確認。

https://tech-master.s3.amazonaws.com/uploads/curriculums//7cd5c7ad844a3308c50d1dfa726d42f2.png

また、nicknameを入力せずにuserの新規登録を行おうとするとエラーが出るか確かめる。

https://tech-master.s3.amazonaws.com/uploads/curriculums//97d70a5a1ee9aa943f891c19080461ab.png

https://tech-master.s3.amazonaws.com/uploads/curriculums//a6d01fc0e3c91b9a2d01bf4fb363aa9e.png

 

STEP7:アソシエーションを利

レビューの保存時に「誰が書いたレビューなのか」という情報を保存できるようにする。また、レビューの表示時にレビューを書いた人のnicknameを表示できるよ実装する。そして、レビューの投稿画面の方のニックネームの入力欄は消してしまう。

 作業内容

1.ニックネームの入力欄を消す
2.userモデルとreviewモデルの間にアソシエーションを設定する

1.ニックネームの入力欄を消す

現在、以下のようにレビューの投稿画面にはニックネームを入力するテキストフィールドがある。

レビューを投稿するユーザーのニックネームはサインアップの段階ですでに設定済みなのでこのテキストフィールドは不要。消してしまう。

 

削除前

app/views/reviews/new.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
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
<div id="main_cnt_wrapper">
  <div id="yjContentsBody">
    <div class="yjContainer">
      <span class="yjGuid"><a id="yjContentsStart" name="yjContentsStart"></a><img alt="ここから本文です" height="1" src="http://i.yimg.jp/yui/jp/tmpl/1.1.0/audionav.gif" width="1"></span>
      <div id="yjMain">
        <article class="section">
          <div class="container">
            <header class="header header--section">
              <h2 class="text-middle">
                <i class="icon-movie color-gray-light"></i>投稿
              </h2>
            </header>
            <div>
              <ul class="listview js-lazy-load-images">
                <li style="margin-bottom: 15px">
                  <a class="listview__element--right-icon" href="#">
                    <div class="box">
                      <div class="box__cell w80">
                        <div class="thumbnail thumbnail--photo">
                          <div class="thumbnail__figure" style="background-image: url(<%= @product.image_url %>);"></div>
                        </div>
                      </div>
                      <div class="box__cell pl1em">
                        <h3 class="text-middle text-break color-sub">
                          <%= @product.title %>
                        </h3>
                        <p class="text-xsmall">
                        </p>
                        <p class="text-xsmall opacity-60"></p>
                      </div>
                    </div>
                  </a>
                </li>
              </ul>
            </div>
          </div>
          <%= form_for [@product, @review] do |f| %>
          <div style="margin: 8px 0">
            <%= f.label :nickname, style: { 'margin-right' => 8 } %>
            <%= f.text_field :nickname, placeholder: 'nickname', value: '' %>
          </div>
          <div style="margin: 8px 0">
            <%= f.label :rate, '評価', style: { 'margin-right' => 8 } %>
            <%= f.number_field :rate, placeholder: '評価', value: 1, max: 10, min: 1, html: { class: "search__query", style: 'text-align: right;' } %>
          </div>
          <div style="margin: 8px 0">
            <%= f.text_area :review, placeholder: 'レビューを書いてね!', style: 'width: 100%;height: 300px;' %>
          </div>
          <div class="row">
            <div class="col10 push1">
              <%= button_tag type: "submit", class: "btn btn--block" do %>
              投稿する<i class="icon-arrow-right"></i>
              <% end %>
            </div>
          </div>
          <% end %>
        </article>
      </div>
      <div id="yjSub">

削除後

app/views/reviews/new.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
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
<div id="main_cnt_wrapper">
  <div id="yjContentsBody">
    <div class="yjContainer">
      <span class="yjGuid"><a id="yjContentsStart" name="yjContentsStart"></a><img alt="ここから本文です" height="1" src="http://i.yimg.jp/yui/jp/tmpl/1.1.0/audionav.gif" width="1"></span>
      <div id="yjMain">
        <article class="section">
          <div class="container">
            <header class="header header--section">
              <h2 class="text-middle">
                <i class="icon-movie color-gray-light"></i>投稿
              </h2>
            </header>
            <div>
              <ul class="listview js-lazy-load-images">
                <li style="margin-bottom: 15px">
                  <a class="listview__element--right-icon" href="#">
                    <div class="box">
                      <div class="box__cell w80">
                        <div class="thumbnail thumbnail--photo">
                          <div class="thumbnail__figure" style="background-image: url(<%= @product.image_url %>);"></div>
                        </div>
                      </div>
                      <div class="box__cell pl1em">
                        <h3 class="text-middle text-break color-sub">
                          <%= @product.title %>
                        </h3>
                        <p class="text-xsmall">
                        </p>
                        <p class="text-xsmall opacity-60"></p>
                      </div>
                    </div>
                  </a>
                </li>
              </ul>
            </div>
          </div>
          <%= form_for [@product, @review] do |f| %>
          <div style="margin: 8px 0">
            <%= f.label :rate, '評価', style: { 'margin-right' => 8 } %>
            <%= f.number_field :rate, placeholder: '評価', value: 1, max: 10, min: 1, html: { class: "search__query", style: 'text-align: right;' } %>
          </div>
          <div style="margin: 8px 0">
            <%= f.text_area :review, placeholder: 'レビューを書いてね!', style: 'width: 100%;height: 300px;' %>
          </div>
          <div class="row">
            <div class="col10 push1">
              <%= button_tag type: "submit", class: "btn btn--block" do %>
              投稿する<i class="icon-arrow-right"></i>
              <% end %>
            </div>
          </div>
          <% end %>
        </article>
      </div>
      <div id="yjSub">

続いて、サインイン中のユーザーを取得してそのユーザーのnicknameをレビューの内容・評価と一緒にReviewモデルに追加する。

 問題7:reviewを新規投稿する際、投稿者のnicknameをreviewsテーブルに保存する

作業ファイル:app/controllers/reviews_controller.rb
ヒント①:reviewを保存するメソッドの引数に、新たに保存したいカラムとその値を追加する
ヒント②:引数の渡し方を変える必要がある

それでは実際に、

評価、レビュー、を記述して投稿し、確認する。

 

https://tech-master.s3.amazonaws.com/uploads/curriculums//202e63dd4c30bac8e7b487a48a4e0d14.png

 

2.userモデルとreviewモデルの間にアソシエーションを設定

nicknameをユーザーとひもづいて設定するようにしたが、今後、レビューとレビューを投稿したユーザーのニックネームだけでなく、アイコンも表示したくなるかもしれない。そのときにReviewsテーブルにカラムを追加することは通常行わない。

あるテーブルのカラムを他のテーブルでも使いたいときに、両方にカラムを追加する方法は好ましくない。データ容量が無駄に増えるし、名前が変わるときに両方のテーブルのカラムを変更しないといけないからだ。

このような場合はアソシエーションを設定する。

アソシエーション

レビューを投稿するときにnicknameを設定するのではなく、レビューを書いたユーザーを設定するようにする。

レビューは書いたユーザーをただ一人持っている。それに対して、ユーザーは複数のレビューを書くことができる。そのため、ReviewモデルとUserモデルの間には1対多の関係がある。

ReviewモデルとUserモデルのアソシエーション

ReviewモデルとUserモデルの間にアソシエーションを設定できれば、Reviewモデルのnicknameカラムは不要となる。なぜなら、nicknameの情報はアソシエーションで取得できるUserモデルのインスタンスがカラムとして持っているから。

1
review.user.nickname

nicknameカラムを消して、アソシエーションを使ってレビューを書いたユーザーのニックネームを取得できるようにする。

また、ReviewモデルとUserモデルのアソシエーションを設定するにはReviewsテーブルにuser_idのカラムが必要になる。user_idのカラムがないとレビューを書いたユーザーがどのユーザーか判断することができない。

Reviewsテーブルのuser_idがNULLのものがあるとエラーが起きる。NULLの部分にUsersテーブルに存在するレコードのidを追加する。

まずは、nicknameカラムを削除。

 reviewsテーブルのnicknameカラムを削除

terminal
1
2
3
4
#reviewsテーブルからnicknameカラムを削除するためのマイグレーションファイルを作成
$ rails g migration RemoveNickNameFromReviews nickname:string
#マイグレーションファイルの実行
$ bundle exec rake db:migrate

 新規作成されるファイル

続いて、reviewsテーブルにuser_idカラムを追加する。

 reviewsテーブルにuser_idカラムを追

terminal
1
2
3
4
#reviewsテーブルにuser_idカラムを追加するためのマイグレーションファイルを作成
$ rails g migration AddUserIdToReviews user_id:integer
#マイグレーションファイルの実行
$ bundle exec rake db:migrate

 新規作成されるファイル

次に、ReviewモデルとUserモデルの間にアソシエーションを設定し、review投稿時にuserとreviewを関連付けるための情報を保存するよう実装する。そして、ビューでreviewを表示する際、関連するuserのnicknameを表示するようビューの記述を書き換える。

 reviewsテーブルのuser_idカラムが空だとエラーが出るので、全てのuser_idカラムに存在するユーザーのidを入れる。

 問題8:reviewとuserの間にアソシエーションを設定する

作業ファイル:
app/models/review.rb
app/models/user.rb
app/controllers/reviews_controller.rb
app/views/products/show.html.erb
ヒント①:モデル間にアソシエーションを設定する記述をする
ヒント②:reviewsテーブルに「そのレビューを投稿したのは誰か」という情報を保存するカラムを追加する必要がある
ヒント③:reviewを保存する際に、先に作ったカラムに情報を保存する実装をする
ヒント④:ビューでは、一つ一つのreviewのインスタンスから関連するuserを取得し、さらにそのuserのnicknameカラムの値を取得する

できたら、rails cコマンドでアソシエーションが正しく設定されているか確認する

terminal
1
2
3
4
5
6
7
8
9
$ rails c

> user = User.find(ユーザーのid)
> user.reviews
# => userの書いたレビューの一覧が表示されるか

> review = Review.find(レビューのid)
> review.user
# => reviewを書いたユーザーが表示されるか

 

STEP8:マイページを実装

最後に今まで自分の書いたレビューの一覧が見られるマイページを実装する。

 作業内容

1.マイページに遷移できるようにする
2.マイページのビューを追加する
3.ユーザーの情報を表示する
4.自分のレビューの一覧を表示する

1.マイページに遷移できるようにする

マイページは、userの詳細ページだということもできる。Railsの7つのアクションでは、詳細ページはshowというアクションにより呼び出す。そこで、新たにusers_controllerを作成し、showアクションを定義する。

terminal
1
2
#users_controllerを作成
$ rails g controller users
app/controllers/users_controller
1
2
3
4
  class UsersController < ApplicationController
    def show
    end
  end

続いてルーティング。

routes.rb
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
TechReviewSite::Application.routes.draw do

  devise_for :users
  resources :users, only: :show
  resources :products, only: :show do
    resources :reviews, only: [:new, :create]
    collection do
      get 'search'
    end
  end

  root 'products#index'

end

次に、マイページに遷移するボタンを作成する。マイページに移動するボタンはヘッダーの「投稿するボタン」と「サインアウトボタン」の間におく。

このボタンを押したときの遷移先は/users/サインイン中のユーザーのidである。呼ばれるアクションは、先ほど作成したUsersControllerのshowアクション

また、ログインしていないのにこのマイページボタンを押されるとユーザーのidがないため困る。そこでログインをしていない時にこのボタンを表示しないようにビューに追記する。

app/views/layouts/review_site.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
25
26
27
28
29
30
31
32
33
34
35
36
<!DOCTYPE html>
<html class="pc" lang="ja" xmlns:fb="http://ogp.me/ns/fb#" xmlns:og="http://ogp.me/ns#">
  <head>
    <meta charset="utf-8">
      <title>映画レビューサイト</title>
      <link href='http://fonts.googleapis.com/css?family=roboto:700,300,400,600' rel='stylesheet' type='text/css'>
      <%= stylesheet_link_tag    "application", media: "all", "data-turbolinks-track" => true %>
      <%= javascript_include_tag "application", "data-turbolinks-track" => true %>
      <%= csrf_meta_tags %>
    </meta>
  </head>
  <body class="yj950-2">
    <div id="wrapper">
      <div id="yjContentsHeader">
        <nav class="globalnav">
          <div class="globalnav__menu">
            <ul class="gmenu">
              <li class="logo" style="float: left">
                <a href="/">mooovi</a>
              </li>
              <% if user_signed_in? %>
                <li class="entry_button" style="float: right">
                  <%= link_to "サインアウト", destroy_user_session_path, method: :delete %>
                </li>
                <li class="entry_button" style="float: right">
                  <a href="/users/<%= current_user.id %>">マイページ</a>
                </li>
              <% end %>
              <li class="entry_button" style="float: right">
                <a href="/products/search">投稿する</a>
              </li>
            </ul>
          </div>
        </nav>
      </div>
      #以下略

 

2.マイページのビューを追加

マイページのビューを作成していく。

コントローラのアクションは、同名のビューファイルを呼び出す。今回はusers_controllerのshowアクションなので、呼び出されるのはviews/users/show.html.erb。

 

ビューファイルに関しては、先ほどダウンロードしたファイルを指定したディレクトリに追加。

追加するファイルは以下のファイルです。

  • rails2-4/users/show.html.erb

 ダウンロードしたrails2フォルダに入っているshow.html.erbファイルを、これから新しく作るviews/usersフォルダに移動

追加するディレクトリ(mooovi)

  •  app
    •  views
      •  users
        •  show.html.erb ←ここに追加

新しく置き換えるファイル(ダウンロードしたrails2-4)

  •  rails2-4
    •  users
      •  show.html.erb

 

3.ユーザーの情報を表示

いまの状態では表示されているユーザーの情報は適当。

 

マイページなので表示する情報は自分の情報にする。マイページ画面で呼ばれるアクションはUsersControllerのshowアクションなので、対応するビューはapp/views/users/show.html.erb

 image_tag

image_tagは、htmlの<img>タグを生成するヘルパーメソッド。以下の例のように引数に文字列で画像ファイルのパスを取る。

sample.html.erb
1
  <%= image_tag "image/sample.jpg" %> #=> <img src="image/sample.jpg">

 問題9:マイページに、ログイン中のuserの情報を表示する

作業ファイル:    
app/views/users/show.html.erb
ヒント:<%= image_tag current_user.avatar %>とすると、ログインしているユーザのアバターを表示することができる

コードを記述したら、さきほどまで適当だったユーザー情報が、自分で登録したユーザー情報になっていることを確認。

 

4.自分のレビューの一覧表示する

最後に表示されているレビューも自分のレビューの情報にする。

 

自分のレビューの情報はアソシエーションを使えば取得できる。
呼ばれるアクションはusers_controllerのshowアクションなので、対応するビューはapp/views/users/show.html.erbとなる。

 問題10:マイページにおいて、自分が投稿したレビューの一覧を表示する

作業ファイル:    
app/views/users/show.html.erb
ヒント:自分の書いたレビューの一覧はUserモデルとReviewモデルのアソシエーションを使って取得する

マイページで、レビューを投稿した作品が表示されていることを確認する。