注意点

  • Rails Tutorialも「とにかく手を動かす」というよりも「基本読み進めて時々写経と僅かな演習問題」というスタイル
  • もっと手を動かしてエラー修正とかググってた方が学習効率上がるような気がする
  • いっそRails Tutorial自体(10章以降)を飛ばしてポートフォリオ作成した方が正解か

この章・節の目的

  • 9.1.4
    • ~9.1.3までの実装のバグ修正(複数タブ・複数ブラウザから2度ログアウト処理が行われた場合の挙動に対処)
  • 9.2 [Remember me]チェックボックス
    • ユーザーの任意選択によりブラウザを閉じてもログイン状態を継続するか否か選択できるようにする
9.2 Remember me 機能実装のモックアップ


Tips

カッコつけるのか、カッコつかないか問題

Rubyでも以下のようなif-then分岐構造を

if params[:session][:remember_me] == '1'  
  remember(user)  
else  
  forget(user)  
end  

三項演算子を用い以下のように記述可能

params[:session][:remember_me] == '1' ? remember(user) : forget(user)  

以前のRubyではremember userと記述できたが、現在は三項演算子ではカッコを省略すると文法エラーになる。


コラム 9.2. 10種類の人々
「この世には10種類の人間がいる。2進法を理解できる奴と、2進法を理解できない奴だ」

和んだ

「頭を柔らかくして考えろ」という示唆に富んだジョークだと解釈。

演習:assignsヘルパー

テスト内部からは

  1. コントローラで定義したインスタンス変数へのアクセスや、
  2. cookiesメソッドにシンボルを使えない等の制約がある

そのため、

cookies[:remember_token]  

常にnilになってしまうが、この問題は

cookies['remember_token']  

上記のように文字列をキーとしたハッシュとして取得することで回避可能。

また、コントローラで定義したインスタンス変数にアクセスできない問題は、
テスト内でのみ使える特殊なassignsヘルパーメソッドにてアクセス可能。

前準備

Sessionコントローラのcreateアクションではuserをインスタンス変数ではなく通常のローカル変数として定義してあるが、これをuser@userとインスタンス変数に変えてしまえば、cookiesにユーザーの記憶トークンが保存されているかテスト可能

その上で、当該テストコード部分を以下のように書き換えた(GREEN)
"test/integration/users_login_test.rb"

  test 'login with remembering' do  
    log_in_as(@user, remember_me: '1')  
    # 演習 コントローラの@user変数にテスト内部からassigns[:user]でアクセス  
    assert_equal cookies['remember_token'], assigns(:user).remember_token  
  end  

Rails Tutorialにはこの演習の模範解答が無いが、テストはGREENで通っているのでたぶん正解。


9.3.2

リスト 9.29: テストされていないブランチで例外を発生する(green)
"app/helpers/sessions_helper.rb"

module SessionsHelper  
︙  
  # 記憶トークンcookieに対応するユーザーを返す  
  def current_user  
    if (user_id = session[:user_id])  
      @current_user ||= User.find_by(id: user_id)  
    elsif (user_id = cookies.signed[:user_id])  
      raise       # テストがパスすれば、この部分がテストされていないことがわかる  
      user = User.find_by(id: user_id)  
      if user && user.authenticated?(cookies[:remember_token])  
        log_in user  
        @current_user = user  
      end  
    end  
  end  
︙  
end  

raiseについてこれ以前でも全く説明がなかった気がするが、本来は後ろに例外クラスの引数を取り任意の例外を明示的に発生させる例外処理用メソッドである模様。

(使用例)

begin  
  raise NoMethodError  
rescue => e  
  puts e  
end  

Herokuデプロイ時のメンテナンスモード
  • ローカルの変更をマージしてHeroku上のアプリを更新する際に、Heroku上でマイグレーションを実行するまで一時的にアクセスできない状態(エラーページ)になる
  • トラフィックの多い本番サイトでは、このような変更を行う前にメンテナンスモードをOnにしておくのが一般的
$ heroku maintenance:on  
$ git push heroku  
$ heroku run rails db:migrate  
$ heroku maintenance:off  

更新作業中一時的にアクセスできなくなる点は同じだが、クライアントにエラーページを見せるよりも一般的なメンテナンス中画面を見せた方が好ましい

9.4.1 本章のまとめ

  • Railsでは、あるページから別のページに移動するときに状態を保持することができる。
  • ページの状態を長期間保持したいときは、cookiesメソッドを使って永続的なセッションにする
  • 記憶トークンと記憶ダイジェストをユーザーごとに関連付けて、永続的セッションが実現できる
  • cookiesメソッドを使うと、ユーザーのブラウザにcookiesなどを保存できる
  • ログイン状態は、セッションもしくはクッキーの状態に基づいて決定される
  • セッションとクッキーをそれぞれ削除すると、ユーザーのログアウトが実現できる
  • 三項演算子を使用すると、単純なif-then文をコンパクトに記述できる
    • ※ただし三項演算子のネストは一般に可読性が悪くなるので避けた方が吉

今日やる予定だった範囲

  • Rails Tutorial 9.1.4~10章

今日やった範囲

  • Rails Tutorial 9.1.4~9章最後まで

反省点

  • やはり学習進度が遅い
  • 手戻り(前の章のソースコードなどへのリンク先再確認など)があるにしてもそれだけではない
  • ただ読むだけならサクサク進みそうなものだが、その「読み流すだけ」が異様に進んでいない
  • Rails Tutorialの学習自体が「ただ読んでいる」時間が長く「手を動かす」量は少ない気がする
  • もっと手を動かして実際の挙動を見ながら公式やググったりで機能実装・エラー修正した方がいい気がする
  • Rails Tutorial10章も同様の状況であればTutorialは中断し書籍『現場で使えるRuby on Rails 速習実践ガイド』を中心にポートフォリオ、オリジナルサイト、(いい感じの)サイト模写に切り替え検討

だがしかし

不満・不足探しの達人になるより、既にあるもの・できていることに焦点を当て感謝といい気分を保とう