オレマトペ

Webエンジニアを目指し学習中のデブアラサーによるほぼ擬音ブログ

Ruby on Rails チュートリアル第7章を終えて

f:id:Npakk:20200610222322p:plain

はじめに

このエントリーでは、Railsを勉強している私がRuby on Rails チュートリアルを学習した感想などを、
各章毎に述べていきたいと思います。
このチュートリアルを学ぶ方法は動画、電子書籍など色々な媒体で提供されておりますが、
ここではWebテキスト(第6版)を使用しております。

目次

第7章 ユーザー登録

さぁやってきました第7章。
もう半分なんですね。
前回はモデルの構造を色々いじってユーザーを登録できる土台をつくって、
さらにはパスワードを認証する機能も作成しました。

今回は実際にユーザー登録を行えるようにUIも含めて実装していくみたい。
がんばりましょー。

まず前段階として、ページのレイアウトにデバッグ情報を追加します。
こうすることによってどのコントローラのアクションが実行されたのかを、
ブラウザに描画されたページで確認することができます。

#application.html.erb

<!DOCTYPE html>
<html>
  .
  .
  .
  <body>
      <div class="container">
        ・
        ・
        ・
      <%= debug(params) if Rails.env.development? %> #ここを加える
    </div>
  </body>
</html>

Erbファイルに上記を加えることにより、開発環境での実行時のみデバッグ情報を確認することができます。

f:id:Npakk:20200627123738p:plain

前章でコンソールからUserを一人作成しましたが、まだアプリケーションにはそのユーザーを表示する機能はありません。
RESTアーキテクチャに従って実装します。
つまりデータの作成、表示、更新、削除をリソースとして扱えるようにします。

今はまだ、users/1というURLにアクセスしてもエラーが表示されるので、
ルートファイルに下記を追加します。

#config/routes.rb

Rails.application.routes.draw do
  root 'static_pages#home'
  get  '/help',    to: 'static_pages#help'
  get  '/about',   to: 'static_pages#about'
  get  '/contact', to: 'static_pages#contact'
  get  '/signup',  to: 'users#new'
  resources :users #ここ
end

これを追加することで、ユーザーのURLを生成するための名前付きルートと、
RESTfulなUsersリソースで必要なアクションの全てが利用できるようになるとのこと。
とりあえずルーティングはできるようになったので、次はページを作成していきます。

Railsの標準的な場所であるapp/views/users/show.html.erbにユーザー名と、メールアドレスを表示する埋め込みRubyを書きます。

#show.html.erb
<%= @user.name %>, <%= @user.email %>

上記はインスタンス変数@userがあることが前提なので、
Usersコントローラのshowアクションに、@userを定義します。

#users_controller.rb
class UsersController < ApplicationController

  def show
    @user = User.find(params[:id]) #ここ
  end

  def new
  end
end

このコントローラにリクエストが送信されると、params[:id]はユーザーIDの1に置き換わり、
User.find(1)を実行したときと同じになります。
実際にアクセスしてユーザー情報が表示されることを確認します。

f:id:Npakk:20200627124212p:plain

上記ではデバッグ情報を確認するためにerbファイルにデバッグコードを埋め込みましたが、
Bybugというgemを使ったデバッグ方法もあります。

#users_controller.rb
class UsersController < ApplicationController

  def show
    @user = User.find(params[:id])
    debugger #ここ
  end

  def new
  end
end

上記を加えると、/users/1にアクセスしたときにコンソール上にデバッグ情報が表示されるようになります。
どう使い分けるかというところまでは言及されていませんが、byebugのほうがより手軽かと思いました。
便利なのはerb埋め込みですかね。

そしてユーザープロフィール画面の表示をもう少し肉付けするために、Gravatarというサービスを利用します。
プロフィール写真を指定したメールアドレスと関連付けすることができるのですが、
これを導入すると写真をアップロードする面倒な作業や、画像をどこに配置するかなどの悩みから解決されるとのこと。

GravatarのURLを返すメソッドをヘルパーメソッドとして用意し、それを使うようにページ画面のerbに埋め込みます。
SCSSで見た目を整えて、最終的には下記のようになりました。

f:id:Npakk:20200627124240p:plain

次はユーザー登録画面です。 form_withヘルパーメソッドをつかって、ユーザー登録に必要な情報を登録するフォームを作成します。
まずコントローラのnewアクションに@userのインスタンス変数を追加します。

#users_controller.rb
class UsersController < ApplicationController

  def show
    @user = User.find(params[:id])
  end

  def new
    @user = User.new #ここ
  end
end

そしてユーザー登録画面にform_withヘルパーメソッドを使用したフォームを実装します。

#new.html.erb
% provide(:title, 'Sign up') %>
<h1>Sign up</h1>

<div class="row">
  <div class="col-md-6 col-md-offset-3">
    <%= form_with(model: @user, local: true) do |f| %>
      <%= f.label :name %>
      <%= f.text_field :name %>

      <%= f.label :email %>
      <%= f.email_field :email %>

      <%= f.label :password %>
      <%= f.password_field :password %>

      <%= f.label :password_confirmation, "Confirmation" %>
      <%= f.password_field :password_confirmation %>

      <%= f.submit "Create my account", class: "btn btn-primary" %>
    <% end %>
  </div>
</div>

詳細は割愛しますが、このヘルパーメソッドを用いて、
モデルとフォームの入力内容を関連付ける働きをしてくれます。

フォームに必要な情報を入力し、submitを押下すると、/usersへPOSTリクエストが送られ、
Createアクションに伝達されます。
Createアクションを下記のように実装します。

#users_controller.rb
class UsersController < ApplicationController

  def show
    @user = User.find(params[:id])
  end

  def new
    @user = User.new
  end

  def create
    @user = User.new(params[:user])    # 実装は終わっていないことに注意!
    if @user.save
      # 保存の成功をここで扱う。
    else
      render 'new'
    end
  end
end

ここで、params[:user}と記載しておりますがここにフォームで入力した値が入ってきます。
また悪意あるユーザーにより操作から守るため、Strong Parametersというテクニックを用います。 リクエストに含まれる属性をそれぞれ許可するかどうかを設定し、
さらにそれをprivateメソッドにして外部からアクセスできないようにするんですね。
必須のテクニックそうですね。

今度はエラーメッセージ表示機能も実装しました。
パーシャルでエラーメッセージを表示するようにerbファイルを書き換えます。 これで、不正な値で登録ボタンをおすとエラーメッセージがユーザー登録画面に表示されるようになりました。

まだ現状ではユーザー登録ボタンを押下してもcreateテンプレートを用意していないため、
有効な値をフォームに入力してもエラーが表示されます。
Createテンプレートを作ってもいいが、ユーザー登録直後はプロフィールページにリダイレクトさせることに。

class UsersController < ApplicationController
  .
  .
  .
  def create
    @user = User.new(user_params)
    if @user.save
      redirect_to @user #ここ
    else
      render 'new'
    end
  end

  private

    def user_params
      params.require(:user).permit(:name, :email, :password,
                                   :password_confirmation)
    end
end

上記で、プロフィールページにリダイレクトしているのですが、あまりよくわからないw
ここは下記のコードの意味と等価みたい。 redirect_to user_url(@user) 実際には、rails側が後者を推察して実行してくれたみたいですが、
こういうのほんとうにややこしい。
省略していくことは便利だが、慣れないうちは勝手になんかやってるとしか捉えられないですよねこれ。

完了したら、ユーザー登録失敗・成功時の総合テストを追加します。
登録リクエスト後にどのページにアクセスするかも含めて、ユーザープロフィールに関するほぼ全ての処理をカバーするようにしていきます。

また、本番環境ではユーザー登録のプロセス中、名前やメールアドレス・パスワードといったデータがネットワークで補足されないようにSSLを導入しました。

あとがき

本格的なアプリっぽくなってきました。
どんどん複雑になっていく内容で、ブログに書くのすら億劫になってきましたw
諦めずにとりあえず最後まで完走したい…