LEFログ:学習記録ノート

leflog: 学習の記録をどんどんアップしていきます

railsチュートリアル10章のまとめ(難しかったところ)

railsチュートリアル10章が終わったのでいつものように難しかったポイントをまとめていきたいと思います。

10章は長いので、この記事も長くなっちゃいそうな気がします。

 

まずはparamsの振り返りです。paramsは現在のユーザーを参照するものだと考えると理解しやすいです。

 

リスト10.20でeditとupdateアクションの保護に対するテストをおこなうのですが、ここで少し詰まったところがありました。

この「test "should redirect update when not logged in" do」でパスワードのアップデートを検証していない理由がよく分かりませんでした。

→おそらくですが、名前とメールアドレスで確認しているので、そこまでする必要がないからだと思います。

 

 

10.2.3でフレンドリーフォワーディングという機能が紹介されます。

この挙動で自分が誤解していたポイントを挙げてみようと思います。

リスト10.29で、フレンドリーフォワーディングのテストがあります。この挙動は、

・編集画面にアクセスする→ログインされていない場合はログイン画面が表示される→ログインすると普通はログイン後のデフォルト画面に移るが、設定を変更しているため、(元々アクセスしていた)編集画面へと自動的に移る。

が正しい挙動になります。

しかし、この挙動は少し複雑です。順を追って説明していきます。

 

まずリスト10.29ですが、このうえのほうに、「class UsersEditTest < ActionDispatch::IntegrationTest」とあります。

よってこれは統合テストだと分かります。

つまり、ハイライト部分の「log_in_as(@user)」は統合テストの方のlog_in_asだと分かります。

log_in_asとはどんな操作だったでしょうか?

チュートリアル9章の、9.3を思い出しましょう。この9.3.1においてlog_in_asヘルパーメソッドを定義しています。

とにかく、log_in_asにおいてセッションを指定してから、ログインすると、それはリスト10.32のcreateアクションへと飛びます(☆セッション指定のログイン操作=セッションコントローラーのcreateアクションです)

→※統合テストのlog_in_asにおいて、セッションが指定されるので、それでcreateされるというわけです。

このcreateアクションでは、有効なメールアドレスとパスワードならそのままログインできて、無効なメールアドレスとパスワードならnewがrenderされるというものです。

(→このcreateアクションの挙動については、8章のリスト8.7や、9章のリスト9.23などを復習すると分かると思います。つまり、sessions_controller.rbにおけるcreateアクションはリメンバー・ミー機能のことです)

createアクションの終わりにredirect_back_or userが追加されたことによって、保存されていたページに飛ぶというわけですね。

 

リスト10.30の「if request.get?」とは何でしょうか?

自分はここを理解するのに苦労しました。自分なりの解釈をまとめてみようと思います。

①postなどでpostした先のurlにリダイレクトされる。

②そのため、ログインしていないままpostやpatchやdeleteを送信すると、ログインした後に「入力が完了しました」「更新されました」「削除が完了しました」などの画面が表示されてしまう

(→しかもログインされてないときに送信しているため、それらの入力は無効である)

③こうした挙動を防ぐために「if request.get?」を使うことで、リクエストした場合のみに限定している。

となります。つまり、ログインする前におこなう操作はGETリクエストに限定しておかないと、おかしな挙動になってしまうというわけですね。実際に操作している姿をイメージすると分かりやすいと思います。

 

また、リスト10.31において大事なポイントがあります。

それはリストの上のほうにあるbefore_actionです。

このbefore_actionがあるからこそ、最初にlogged_in_userとcorrect_userが呼び込まれるため、store_locationが発動するわけです。beforeアクションについては前の章に書かれていたと思うので、自分のように忘れている方は復習してみてください。

 

さて、リスト10.33のあとの演習です。

この演習1の答えは、間違っているものが多かったです。

具体的には、assert_redirect_toを削除している解答が多かったです。これは削除しないほうがいいと思います。

assert_redirect_toは削除せずに残したままのほうが、ちゃんとした答えだと思います。

らくだ🐫にもできるRailsチュートリアル|10.2 | らくだ🐫のさいと
https://rakuda3desu.net/rakudas-rails-tutorial10-2/

たびたびお世話になっている↑のサイト様ですが、この解答が一番正しいと思います。

[users_edit_test.rb]

  test "successful edit with friendly forwarding" do
    # edit_user_path(@user)にgetのリクエス
    get edit_user_path(@user)
    # session[:forwarding_url]とedit_user_url(@user)が等しい時にtrue
    assert_equal session[:forwarding_url], edit_user_url(@user)
    # @userとしてログイン
    log_in_as(@user)
    # edit用のテンプレートはリダイレクトで描画されるので下記一文は削除
    # assert_template 'users/edit'
    # session[:forwarding_url]がnilの時true
    assert_nil session[:forwarding_url]
    # @userのユーザー編集ページにリダイレクトされる
    assert_redirected_to edit_user_url(@user)
    # nameに"Foo Bar"を代入
    name  = "Foo Bar"
    # emailに"foo@bar.com"を代入
    email = "foo@bar.com"
    # 有効なparams:を持ったuser_path(@user)でpatch(更新)のリクエス
    patch user_path(@user), params: { user: { name:  name,
                                              email: email,
                                              password:              "",
                                              password_confirmation: "" } }

見づらくてすみませんm(_ _)m

 

そしてこの演習2なのですが、debuggerの使い方を思い出す必要があります

自分はすっかり忘れてしまっていたので、後日復習しようと思います。

 

 

レイアウトの統合テストについてです。

リスト10.41の次に演習が有り、そこで「レイアウトにあるすべてのリンクに対して統合テストを書いてみましょう」という問題があります。

この統合テストをどうやって書けばいいのかよく分かりませんでした。というより、何を手掛かりにしてどこから書いていけばよいのかに対する基準が分からなかったというか……

で、答えは簡単です。

「レイアウトにリンクに対しての統合テストは、実際の画面を見ながら書き込んでいく」ということです。つまり、Railsコンソールで起動して、実際の画面を元にリンク先をチェックして、それをもとにコードを書いていけば良いというわけですね。

あるいは単純に「リスト10.40のようなレイアウトのhtmlを参照にしてコードを書いていく」のだと思います。とりあえず、レイアウトのディレクトリ内を参考にしていけば良いのではないかと推測しています。

ここで気をつけることは、ログインしているときとログインしていないときのどっちのテストも書く必要があるということです。

らくだ🐫にもできるRailsチュートリアル|10.3 | らくだ🐫のさいと
https://rakuda3desu.net/rakudas-rails-tutorial10-3/

 

 

リスト10.56です。これは演習で、admin属性が変更できないことを確認しています。

これはStrong Parametersに関する内容です。

演習のすぐ上にあるコードを見てみましょう。

ここで、def user_paramsのpermitで:name, :email, :password, :password_confirmation以外の項目をいじれないように設定しています。だから、adminはいじれないようになっているのです。

逆に言えば、adminの項目を追加したら、いじれるようになってしまいます。

ちなみにこのコードは、「usersコントローラー内のuser_paramsメソッド」にあります(リスト7.19)。

 

リスト10.57に<% if current_user.admin? && !current_user?(user) %>というコードがあると思います。

この読み方がよく分からなかったので調べたところ、こんな記事が見つかりました。

if current_user.admin? && !current_user?(user)で「!」が必要な理由 - Qiita
https://qiita.com/kaino5454/items/7693c469f38ea05aeb04

つまり、「current_userが管理者であり、なおかつrenderで一つ一つチェックされているuserがcurrent_userで無い限り」という意味ですね。

管理者であるcurrent_userが自分自身をdeleteしてしまったらマズイので、こうしているわけです。

 

 

少し飛んでリスト10.62に移ります。

ここで、test "index as non-admin" doで始まるブロックのテストの中に、「assert_select 'a', text: 'delete', count: 0」というコードがありますね。

これは、同じリストの中の別のテストの「assert_select 'a[href=?]', user_path(user), text: 'delete'」とは形が異なっています。

特に'a'の部分が分かりにくいです。どうしてこれは'a[href=?]'になっていないのでしょうか?

答えはおそらく、このtest "index as non-admin" doにおいては、リンク先の指定がないからでしょう。例えばa[href=?]があるテストの場合は、その次にuser_path(user)などのリンク先の指定があります。

しかし、このテストにおいては、リンク先の指定がありません。だからこそ、'a'だけでも大丈夫というわけです。

管理者ではないので、deleteは表示されません。ここではdeleteが表示されないことだけを確認すればいいので、このようなコードになっているのだと思います。

→ちなみに'a'は「<a>タグ」のことです。リンクを指定する場合に使用するタグです。

 

ちなみに同じリスト内の、「unless user == @admin」とは、adminユーザー以外に対してassert_selectで確認しているということです。adminユーザに対しては、deleteが表示されないため、確認する必要がないので。

 

10章で難しかったポイントは以上になります。

以下に参考にした記事のリンクを貼っておきます(順番は適当に)。

特に10章で参考になったのはラクダ様の記事でした。感謝致します。

→演習の答えはラクダ様の記事が一番分かりやすく、なおかつ正確でした。

 

 

railsアプリでログインをされていないユーザーをログイン画面に飛ばす - Qiita
https://qiita.com/daikiganba/items/a23f80085cd2b8cc6f68

 

Rails Sessionの実装② - Qiita
https://qiita.com/mamika311/items/8609ae78c7a6d1fee0b9

 

静的型付け言語原理主義者によるRailsチュートリアル(第10章)
https://sore8sore104te.com/rails-tutorial-chapter10/

 

らくだ🐫にもできるRailsチュートリアル|10.4(と10.5) | らくだ🐫のさいと
https://rakuda3desu.net/rakudas-rails-tutorial10-4-10-5/

 

らくだ🐫にもできるRailsチュートリアル|9.3(と9.4) | らくだ🐫のさいと
https://rakuda3desu.net/rakudas-rails-tutoria9-3-9-4/

 

【初心者向けまとめ】flashメッセージの理解と実装 - Qiita
https://qiita.com/Toshimatu/items/008be17d5d0659ea9dc0

 

if current_user.admin? && !current_user?(user)で「!」が必要な理由 - Qiita
https://qiita.com/kaino5454/items/7693c469f38ea05aeb04

 

Rails・assert_selectの色々な指定の仕方 - Qiita
https://qiita.com/shumpeism/items/06332cb4ced1c15cb09c

 

Rails チュートリアル 【初心者向け】 テストを10分でおさらいしよう!  - Qiita
https://qiita.com/duka/items/2d724ea2226984cb544f

 

assert_redirected_to | Railsドキュメント
https://railsdoc.com/page/assert_redirected_to

 

RailsRailsのテストって難しい。Railsチュートリアルにも出てくるテストについて|Jyu2ログ
https://jyu2log.com/rails-test

 

RailsのStrong Parametersを調べる - Qiita
https://qiita.com/mochio/items/45b9172a50a6ebb0bee0

 

Railsチュートリアル 第9章 発展的なログイン機構 - [Remember me] のテスト - Qiita
https://qiita.com/rapidliner00/items/74e44310e62ee03cd978