LEFログ:学習記録ノート

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

railsチュートリアル7章の振り返り(難しかったところ)

railsチュートリアルの7章が終わったので、自分なりに難しかったところをまとめていきたいと思います。

 

7章ではユーザー登録について学んでいくことになりました。

まずはデバッグ情報を画面上に追加する方法です。

ここではdebugというメソッドと、paramsという変数の2つの概念が登場します。

 

リストの7.3でUsersリソースをroutesファイルに追加することで、RESTfulなアクションを利用できるようになるということですが、この後のところに少しだけ難しいところがありました。

/user/1にアクセスしたときに表示されない問題を防ぐため、「app/views/users/show.html.erb」を追加するわけですが、その理由がぼんやりとしか理解していませんでした。

 

new.html.erbを追加した時……つまり本文中にも書かれているように、リスト5.38から始まる一連の流れを思い出す必要があります。

ここでUsers newでgenerateしたときは、new.html.erbが自動的に追加されました。そして、リスト5.39では既にdef newとしてコントローラもできあがっています。

そして、リスト5.43において、/signupのルーティングも行っています(users#new)。

 

つまり、「ルーティングをすることと、ビューを作ることは、セットでおこなわなければならない」という洞察を得ることができます。

考えてみたら当たり前のことですが、こうした基本をしっかり理解していないとこんがらがってしまうのでまとめてみました。

 

そして次のリスト7.5です。ここではdef showのあとに、@user = User.find(params[:id])というコードを書かなければなりません。

これはユーザーが増えていくと、idが1,2,3,4,...と増えていくため、一つに決めることができないからです。

それぞれのユーザーごとに、それぞれのアクションをする必要があります。

そのために必要なのが、「params」というメソッドです。

(たぶん合ってるはず……汗)

 

また、ここでdebuggerというメソッドが出てきます。

これはdebugメソッドよりももっと直接的な方法です。ターミナルから色々とデバッグできるらしいです。

 

gravatarが登場します。これを使うと、ユーザーのプロフィール画像を簡単に設定できるようになるというわけです。

また、チュートリアルの通りにサイドバーを追加することで、見栄えも良くなります。

 

次はユーザー登録です。

自分は第5版を読んでいるので、form_forを学びました。後に第6版でform_withを学ぶ予定です。

 

ユーザー登録フォームを作っていくわけですが、ここでnew.html.erbに変更を加えることになります。また、フォームに対応するcssも書いていきます。

 

renderメソッドもこの後に出てきます。これはなんだっけ?と一瞬戸惑い、本文のとおりに5.1.3を再確認。

リスト7.1.8に出てくる「render 'new'」というコードは、これはつまりその上の「def new」のところを参照している、ということっぽいです。

つまり、@user.saveが実行不可であったとき、@user = User.newが実行されるというわけですね。

 

ここでひとつ疑問が浮かびます。

   if @user.save
      # 保存の成功をここで扱う。
    else
      render 'new'

このコードを見たときに、不思議な感じがしました。ifの次に@user.saveがあるわけですが、ifの前に@user.saveはされていません。

つまり、@user.saveがされているかどうか、はどうやって確認しているのかと。postされただけではsaveされてはいないだろうし……

自分の抱いたこの疑問は、他の人が既に検証済みでした。その記事を以下にシェアいたします。

[Rails]saveメソッドはif文でも実行されるのでuser.saveとかは省略可 | ぼくらの研究
https://bokuranotameno.com/post-9555/

https://bokuranotameno.com/post-9555/

 

これ……if文実行したときに、自動でsaveメソッド実行されてますよね?

(中略)

結論:saveメソッドはif文でも実行される。なのでuser.saveとかは省略可

 

やっぱり、このif文の前にsaveメソッドは実行されていません。どうやら、if文を書くと、そこでsaveメソッドが実行されるらしいです。

これを自分なりにまとめると、

「if @user.save」とは、「@user.saveが既にされているかどうか」ではなく「@user.saveを実行する&それができたかどうか」を確認するコードである

と、なります。

これは小さなトラップですね(汗)

 

チュートリアルを読んでいくと、次にuser_paramsなどの説明が出てきます。これは権限の乗っ取りを防ぐための措置らしいです。なるほどなるほど。簡単にまとめると、admin='1'のような管理者権限をいじられないようにするための方法でした。

 

7.3.4失敗時のテストにおける演習はちょっと難しかったです。

まずリスト7.25ですが、この答えがよく分かりませんでした。

ネットに散らばっている様々な解説記事を読んだところ、どうやら答えは

  assert_template 'users/new'                                                   # newアクションが描画(つまり@user.save失敗)されていればtrue、なければfalse
  assert_select   'div#error_explanation'                                       # divタグの中のid error_explanationをが描画されていれば成功
  assert_select   'div.field_with_errors'                                       # divタグの中のclass field_with_errorsが描画されていれば成功

であることがわかりました。

Ruby on Rails チュートリアル 第7章 ユーザー登録機能からflash テスト駆動開発や通信のSSL化を解説 - Qiita
https://qiita.com/bitcoinjpnnet/items/914c2d2b4ff2c08b2f5b

Ruby on Rails チュートリアル をやってみた その10 - IxD's blog
https://ixd.hatenablog.jp/entry/2016/03/18/080000

を参考にしました。

 

ここでの assert_select   'div.field_with_errors' は、divの後ろにドット(.)が入っているので注意が必要です。

つまり、リスト7.22のcssのインテンドされていない目立ってる部分を書けば良いというわけですね。

それをassert_selectで確認すれば、エラーメッセージをテストできるというわけです。

 

別解としては、

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

【第7章】Ruby on Rails チュートリアル 5.0(第4版)演習と解答まとめ - 新米パパの育児留学
https://mochikichi.hatenablog.com/entry/2017/02/19/203320

の2つを見つけましたが、これは両者ともdiv.の後ろがalartになっていました。

もしかすると、この2つは参照しているrailsチュートリアルのバージョンが違うのかもしれません。自分は現在第5版で勉強しています。

 

同じ演習の2番です。

これもちょっと読み取りにくかったのですが、答えは次のようになります。

routes.rbにpost ‘/signup’, to: ‘users#create’を追加
→/signupにpostのリクエストをしたらusersコントローラのcreateアクションを実行
users/new.html.erbのフォームに送信先アドレスを指定
→<%= form_for(@user, url: signup_path) do |f| %>(第2引数で指定)

→postリクエストのsignup_pathに関するテストは書かれていないから
 (テストされていないからREDが出るはずもない→GREEN)

下の2つの記事の中程を参考にしました。

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

 

Ruby on Rails チュートリアル 第7章 ユーザー登録機能からflash テスト駆動開発や通信のSSL化を解説 - Qiita
https://qiita.com/bitcoinjpnnet/items/914c2d2b4ff2c08b2f5b

これを自分なりにまとめますと、おそらく、postを実行したときに/sign upにいると(/sign up上でpostを実行すると)、users#createが発動します。そして、リスト7.27で追加したコードにより、url: signup_pathへと送信されるようになっています。

→追記:「/signupへとポストすると、users#createに対応したURLに行く」のほうが正しいような気がしてきました。

 

でも、どうしてだからといって、無効なユーザー登録データを送付してもどちらのURLも/signupになるのか、よく分かりません。特にルーティングのところが、うまく理解できず……。

自分の推測としては、url: signup_pathへと送信されたことで、自動的にそこへと追尾する(移動する)から、どちらのURLも同じになる……ってことかな~と思いました。

いや、それともルーティングのところの、user#createが実行されることで、このcreateに対応するURLに固定されるということかな。うーん。(・・?

後日、しっかり調べてみたいと思います。

 

分からないところは、後日振り返ると十全に理解できたりします。これはおそらく、全体像を把握することで、細部の仕組みも分かってくるからだと思います。

 

次にflashという特殊な変数が出てきます。

どうしてflashを使うのかと言うと、まさしく「閃光」のように、一度だけしか表示しないからだと思われます。

よくネットとかでログインに成功したりすると、一時的に「ログインに成功しました!」みたいなメッセージが画面に表示されることがあると思います(再読み込みすると消えちゃうやつです)。そのような、一時的に表示したいメッセージがあるときに、flashを使うわけです。

また、flashは、「:success」のようなシンボルを文字列に変換することもできます。そのことによって、div classのところに、「alert-success」が入れられるようになります。こうすることで、cssを記述するときに、このalert-successのところをいじれるようになるわけですね。

 

次に「assert_difference 'User.count', 1 do」が出てきます。

これも最初は何を意味しているのかよく分かりませんでした。いや、意味は分かるのですが、このコードの書き方(特に右側の数字の部分)が直感的に把握できなかったと言うか……

ここでは、「成功時のテスト」を扱っています。つまり、ユーザー登録を1回おこなうと、ユーザの数は1つ増えます。その差異(増減)は1つだけなので、右側に「1」を入れているわけです。

もし、テスト内で2つ分のユーザ登録をしたら、assert_difference 'User.count', 2 doになるのだと思います。また、差異を気にせず違いだけを確認する場合は、そもそも数字を書かないのだと思います。

「follow_redirect!」で追尾して、「assert_template 'users/show'」で追尾先の画面を確認して終わりです。

 

あとは最後にSSLの説明があります。今までSSLについてよく知らなかったので、勉強になりました。

 

 

7章で一番難しかったのは、7.3.4失敗時のテストの演習の2番です。

この演習のリスト7.26と7.27が漠然としか理解できていません。おそらくルーティングに対する理解が不足しているのだと思います。

「post '/signup',  to: 'users#create'」は/signupのURLへとpostすると、usersのcreateのページに行く(発動する)。だと思うのですが、それでどうして後に/signupになるのかと言われるとちょっとよく分からなくて……

users#createのページが、 <%= form_for(@user, url: signup_path) do |f| %>によって、signup_pathになっているから。なぜなら、signup_pathが送信先になっているということは、そこがusers#createのページになっているから。

というのが自分が仮に出した一時的な結論です。

ルーティングが指定されていない時は、 resources :usersによって、自動的に/usersになってしまうのでしょう。おそらく。

 

いや、railsチュートリアルを自力で勉強するのはなかなか難しいです。

でもそれ以上にとても楽しいという気持ちがあります。ちょっと難しいゲーム……というか工作をしているような感覚です。

たとえその場で分からなくても、仮定を出して進めていく。そうすると、後で振り返ったときにその仮定が正しかったのかを検証できますし、一時的な仮定を出すことで前へと前進することができます。

これは理系の研究者が、とりあえずの仮説のもとで理論を作り、のちに実証実験によってその理論が正しいのかを精査する作業に似ていると思います。その理論が仮に間違っていたとしても、それが当座のところ有効に機能していれば、有用性はある程度担保されます。プラグマティズム

 

また、ブログにこうしてまとめることで、さらに理解が深まっている気がします。ただ漫然と読んでいるだけでは、読んだそばから忘れていってしまう気がします。

 

さて、次からは8章です。加速度的に難易度が上がっている気もしますが、それでも以前予測していたよりは簡単な気もします。心が折れないように頑張って行きたいと思います。

 

 

追記:参考にしたその他の記事いろいろ(6章までのものも含みます)

Rails】paramsってなんだ? - Qiita
https://qiita.com/sleepy_cat/items/c8eecfc5c486b0f7f2b8

 

Ruby on Rails - Rails オプション引数とキーワード引数の違い、優先順位|teratail
https://teratail.com/questions/193142

 

assert_not と vlaid? を使い validation が有効かどうか確認するテスト 6.2.2 存在性を検証する - Qiita
https://qiita.com/nyankote/items/e5a661b0fa2f521072d4

 

Git で「追跡ブランチ」って言うのやめましょう - Qiita
https://qiita.com/uasi/items/69368c17c79e99aaddbf

 

マイグレーション (migration)とは|「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典
https://wa3.i-3-i.info/word17035.html

 

【 git push 】コマンド(基礎編)――ローカルリポジトリの内容をリモートリポジトリに送信する:Linux基本コマンドTips(397) - @IT
https://atmarkit.itmedia.co.jp/ait/articles/2005/21/news023.html

 

Rails ルーティング 基礎 まとめ - Qiita
https://qiita.com/akk11_k/items/a6a21beb2b736ebbc147

 

Rails】ルーティングの色々な作成方法をざっくりまとめてみた
https://zenn.dev/yukihaga/articles/69a816962ef6b9

 

万能タグdivタグは「class属性」で使いこなそう--人気ホームページが作れる簡単作成講座
http://homutuku.com/beginner/440.html

 

git - bitbucketに公開鍵を設定したのにpush時にパスワードを求められる - スタック・オーバーフロー
https://ja.stackoverflow.com/questions/250/bitbucket%E3%81%AB%E5%85%AC%E9%96%8B%E9%8D%B5%E3%82%92%E8%A8%AD%E5%AE%9A%E3%81%97%E3%81%9F%E3%81%AE%E3%81%ABpush%E6%99%82%E3%81%AB%E3%83%91%E3%82%B9%E3%83%AF%E3%83%BC%E3%83%89%E3%82%92%E6%B1%82%E3%82%81%E3%82%89%E3%82%8C%E3%82%8B