まさ@ブログ書き込み中

まさ@ブログ書き込み中

まさの旅、英語、プログラミング、プライベートについて、色々記録しています。

セッション使ったことあるのにRailsチュートリアル8章が目から鱗すぎる

 

こんにちは。まさです。

ジョークを交えた挨拶も思い浮かばないくらいRailsチュートリアルを1日でも早く終わらせることに集中してます。

 

今回は8章基本的なログイン機構について書いていきます。

 

より具体的には

この第8章と第9章を通して、1: ブラウザを閉じるとログインを破棄する (Session)、 2: ユーザーのログイン情報を自動で保存する (Cookie)、3: ユーザーがチェックボックスをオンにした場合のみログインを保存する (Remember me) 、という3つの一般的なログイン機構を実装することになります。

 

では早速まとめていきます。

 

 

セッション

セッションとは

HTTPはステートレスなプロトコルなので、ユーザーログイン後にユーザー情報を保持し続ける必要がある場合、セッションと呼ばれる接続を別途設定します。

 

ここで僕があえて紹介したいのは訳注によるセッションに関する補足説明です。本章には以下のように書かれていました。

訳注: 昔は離れた相手と一手ずつ葉書をやりとりしてのんびりと将棋を指す酔狂な人がときどきいましたが、将棋の対戦を1つのセッションと考えれば、その下の郵便システムはHTTP同様ステートレスであり、対戦者同士が盤の状態を保持していれば、郵便システムや郵便配達夫が対戦の進行や内容に一切かかわらなくてもゲームは成立します

 

見た瞬間、僕は

わかり易すぎだろ。

と思いましたね。

 

さて、セッションがどういうものか掴んだあとはそれを実装する方法について大まかに理解しましょう。

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

 

ただし、本章ではRailssessionメソッドを使って一時セッションを作成します。ブラウザを閉じると自動的に終了してしまうことが、「一時」と呼ばれる理由です。

 

一時セッションを実装する

セッションを実装する際の方向性としてセッションをRESTfulなリソースとしてモデリングします。

ログインページではnewで新しいセッションを出力し、そのページでログインするとcreateでセッションを実際に作成して保存し、ログアウトするとdestroyでセッションを破棄する

という風にやっていきます。

 

まずはSessionsコントローラとnewアクションを生成します。対応するビューが必要なのはnewアクションだけだからです。

$ rails generate controller Sessions new

 

また、RESTfulアクションを実現するために、ルートファイルで以下のコードを書き加えます。

  get    '/login',   to: 'sessions#new'
  post   '/login',   to: 'sessions#create'
  delete '/logout',  to: 'sessions#destroy'

 

セッションフォームは、ユーザー登録フォームで使うform_forヘルパーメソッドへ与える引数が:session, url:hoge_pathになる点で異なります。

 

ユーザー登録時

form_for(@user)

ログイン時

form_for(:session, url: login_path)

 

上のコードのおかげでフォーム送信後にparamsハッシュに入る値が、メールアドレスとパスワードのフィールドにそれぞれ対応したparams[:session][:email]params[:session][:password]になります。

 

 

セッションと関連させたログイン

さて、Sessionsコントローラー(とnewビュー)を作成し、フォームからsessionメソッドにデータを送信する準備が整いました。

 

次は、ログイン時にセッションを開始しなければなりません。といってもそれはシンプルで、今までのログイン認証が成功したときに

    session[:user_id] = user.id

といった形でsessionというハッシュにユーザー情報を入れればいいのです。

 

また、ログアウトは

session.delete(:user_id)

とするだけでOKです。

 

 

フラッシュ

ログインフォームを入力し情報を送った結果、なんらかのメッセージを表示したいことがあります。サクセスメッセージやエラーメッセージがそうです。

 

そのときに使えるのがフラッシュメッセージです。フラッシュメッセージは、一度表示された後に他のページなどに遷移したり、同じページが更新されると(リクエストが起こると)消えてしまうメッセージです。

 

ユーザー登録の際のエラーメッセージは、Active Recordオブジェクトに関連づけられていたエラーメッセージを使っていたので、特にメッセージを考えなくてよかったのですが、セッションの場合はActive Recordのモデルを使っていない(データベースで作成や削除を行なっていない)ため、フラッシュメッセージを利用するのです。

 

例えばログインに失敗したら

      flash[:danger] = 'Invalid email/password combination'

と書くようにすればOKです。

 

実は僕もLINE風アプリケーションMINEを作った際にこのフラッシュを利用していましたが、馬鹿の一つ覚えでメッセージを表示したい場合には片っ端からこれを使っていました・・・。

 

しかし、上のコードでは十分ではありません。これだと

リダイレクトを使ったときとは異なり、表示したテンプレートをrenderメソッドで強制的に再レンダリングしてもリクエストと見なされないため、リクエストのメッセージが消えません。

といった問題が起きます。

 

その対策として上のコードに少し書き加えて

      flash.now[:danger] = 'Invalid email/password combination'

とするのが良いとされています。

 

過去の僕は確かいちいちリダイレクトさせてた気がします・・・。

 

 

Rails的な書き方

最後に、本書全体を通して僕が学んだRailsならではの発想やコードの書き方を改めてまとめていきたいと思います。

ヘルパーメソッド使いまくり

これまでも死ぬほどやってきたことですが、言及するのを忘れていました。どうやらRailsではよくヘルパーメソッドを設定して使うようです。

 

Railsチュートリアルではテストの際にもたくさんのヘルパーメソッドを使うので、余計に多い気がします。

 

何度も使うメソッドであれば、ヘルパーメソッドとして用意しておいたほうが良いですね。

 

例えば、Sessionsヘルパーには以下のようなlog_inメソッドが定義されています。

  # 渡されたユーザーでログインする
  def log_in(user)
    session[:user_id] = user.id
  end

 

Railsの自動コード変換に頼ったコードの書き方

form_forヘルパーメソッドについて書いたときにも言いましたが、Railsは勝手に判断して自動でコードを変換する機能があります。

 

本章では

      log_in user
      redirect_to user

と書くところがありましたが、これは実際にはlog_in userlog_in(user)の意味で、redirect_to userredirect_to user_url(user)として変換されるようです。

 

 

今回のところはこれで終わり。ではまたー。