0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

わたしがRailsチュートリアルで学んだこと【8章】

Last updated at Posted at 2019-07-14
  • 注意:プログラミング歴34日の初心者が書いています

  • 注意:間違っていたら優しく教えてください(喜びます)

「Ruby on Rails チュートリアル実例を使ってRailsを学ぼう」
https://railstutorial.jp/

素晴らしいチュートリアルに感謝します。

#8.1 セッション

HTTPは、その場限り。以前の情報を全く持たないリクエストです。
そのため、ログイン情報の保持には、セッションという接続を使います。

Railsでセッションを実装する方法として最も一般的なのは、cookiesを使う方法です。cookiesとは、ユーザーのブラウザに保存される小さなテキストデータです。

セッションについても例に漏れず、Sessionsコントローラで操作します。

コントローラを追加したら、routes.rbに対応するルーティングを追加します。今回は、

  • new 新しいセッションのページ (ログイン画面)

  • create 新しいセッションの作成 (実際のログイン)

  • destroy セッションの削除 (ログアウト)

という3つのアクションを、/loginというURLに紐づけます。

#8.1.2 ログインフォーム

フォームに入力されたログイン情報を保存したい、でもセッションにはUserのときのようなモデル、データベースはありません。

form_for(:session, url: login_path)

そのため上記のように、データを保存するリソース名(ここでは:session)とそのパスを指定ながら、form_forでformタグを生成します。

rb
<%= form_for(:session, url: login_path) do |f| %>

      <%= f.label :email %>
      <%= f.email_field :email, class: 'form-control' %>

      <%= f.label :password %>
      <%= f.password_field :password, class: 'form-control' %>

      <%= f.submit "Log in", class: "btn btn-primary" %>
    <% end %>

送信されたデータは、

  • params[:session][:email]

  • params[:session][:password]

で受け取ることができます。こうしてみると、リソース名(ここでは:session)をシンボルで記述する意味がわかりますね。

"session" => { 
            "email" => "foo@bar.com",
            "password" => "something",  
          }

送信されるデータはこういうハッシュになってるということですね。

これが、login_pathのPOST、つまりcreateアクションに受け渡されるということです。

#8.1.3 ユーザーの検索と認証

sessionコントローラのcreateアクションでparamsからデータを受け取ることができます。

##renderredirect_toについて

flashで表示させるエラーメッセージは、redirect_toの場合は次のページ移動で消えるのに、rederではページ移動しても消えずに残ったままになってしまう。

renderを使用する場合はflash.nowを使う。

###renderとは

  • renderは指定したviewを呼び出します。
  def new
  end

これも実はrenderが動いています。
GETアクション内になにも記述がない場合は、

  def new
    render 'new'
  end

に勝手に補完されています。

###redirect_toとは

  • redirect_toはHTTPリクエスト(GET)をサーバーに送ります。
def create
    @user = User.new(user_params)
    if @user.save
      flash[:success] = "Welcome to the Sample App!"
      redirect_to @user
    else
      render 'new'
    end
  end

わかりにくいですが、ここでもRailsの自動補完が効いているのでした。
redirect_toの行は、以下と同じ意味です。

redirect_to user_url(@user)

#8.1.5 フラッシュのテスト

require 'test_helper'

class UsersLoginTest < ActionDispatch::IntegrationTest

  test "login with invalid information" do
    get login_path #1
    assert_template 'sessions/new' #2
    post login_path, params: { session: { email: "", password: "" } } #3
    assert_template 'sessions/new' #4
    assert_not flash.empty? #4 flashはemptyでない
    get root_path #5
    assert flash.empty? #6 flashはemptyである
  end
end
  1. ログイン用のパスを開く
  2. 新しいセッションのフォームが正しく表示されたことを確認する
  3. わざと無効なparamsハッシュを使ってセッション用パスにPOSTする
  4. 新しいセッションのフォームが再度表示され、フラッシュメッセージが追加されることを確認する
  5. 別のページ (Homeページなど) にいったん移動する
  6. 移動先のページでフラッシュメッセージが表示されていないことを確認する

#8.2 ログイン

##ApplicationコントローラにSessionヘルパーモジュールを読み込む

ApplicationコントローラにSessionヘルパーモジュールを読み込むと、他の全てのコントローラで使用できるようになります。
それは、他の全てのコントローラが、Applicationコントローラを継承しているからです。

#8.2.1 log_inメソッド

##sessionメソッドについて

session[:name]

sessionメソッドはRailsにあらかじめ組み込まれているメソッドです。
名前をつけて、セッションに登録できます。

これは、8章冒頭に自分でrails -gして作ったSessionsコントローラとは無関係です。

module SessionsHelper

  # 渡されたユーザーでログインする
  def log_in(user)
    session[:user_id] = user.id #user.idを`:user_id`という名前で保存
  end
end

どのviewでも使うことができるように、ヘルパーに関数を定義します。
sessionメソッドで作成した一時cookiesは自動的に暗号化されます。すごい。

##ブラウザからcookiesの情報を調べてみてください。の演習について

AWS Cloud9を使っている人は、amazonawsでcookies検索すると出るかと思います。

#8.2.2 現在のユーザー

##「例外を発生させる」or「例外を発生させない」

User.find(session[:user_id]) #例外が発生する
User.find_by(id: session[:user_id]) ##例外が発生しない(nillを返す)
  • findメソッドは例外を発生させて処理を中断する。

  • find_byメソッドはnilを返すため処理は中断されない。

「ユーザページの表示」の場合は、ユーザーのidが無いのは「例外」です。(表示するページもなにもない)

一方、「ユーザーのログイン」の場合、まだログインしていないなど、クッキーにデータがあったりなかったり、両方の状態が考えられます。そのため、「例外」での処理はしません。

##現在のユーザーを定義する

  def current_user
    if session[:user_id]
      @current_user ||= User.find_by(id: session[:user_id])
    end
  end

「もし、session[:user_id]が存在するなら、
@current_usernillならUser.find_by(id: session[:user_id])を代入する」

 @current_user ||= User.find_by(id: session[:user_id])

上記は、以下と同じです。

if @current_user.nil?
  @current_user = User.find_by(id: session[:user_id])
else
  @current_user
end

まず、@current_usernilかどうか(値があるかどうか)チェック。
@current_usernil(つまりログインしてない)なら、セッションIDからuserを検索して@current_userとします。

もし@current_usernilでないなら、すでにログイン中ですので、そのまま@current_userを返します。

#8.2.3 レイアウトリンクを変更する

ログインしている場合orしていない場合で、レイアウトを変更します。
view内で、ifを使って表示する内容を変える。

ifの条件分岐を使用して、current_userがtrueかfalseか(ログインしているか否か)で分岐させます。

ユーザーがログイン中の状態とは「sessionにユーザーidが存在している」こと、つまりcurrent_userがnilではないという状態を指します。

# ユーザーがログインしていればtrue、その他ならfalseを返す
  def logged_in?
    !current_user.nil?
  end

ログインしているかどうかを確かめるメソッドをヘルパーに定義して、便利にすぐ呼び出せるようにしておきます。

truefalseなど真偽値を返すメソッドは名前に「?」をつけて置くのがルールです。

#リスト 8.21: fixture向けのdigestメソッドを追加する

全く意味がわかりません。誰かたすけてください。

#8.3 ログアウト

session.delete(:user_id)

上記のdeleteメソッドでセッションを削除できます。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?