ぞえの技術めも

Ruby on Rails勉強中

【187日目】【1日20分のRailsチュートリアル】学習を終えて

Ruby on Railsチュートリアル(第3版)」の学習も先日ようやく最後まで辿り着きました。 学習を開始したのは2016年07月07日のことなので、期間としては約1年3ヶ月かかったことになります。
日数としては記事タイトル通り「186日」ですね。毎日すれば半年とちょっと。

kt-zoe.hatenablog.com

当初はWebアプリ作りたかったのか…(忘れてた)

基本会社の昼休みに学習→ブログ更新していたので、最大週5日の学習でした。しかも1日約20分。とてものんびり。
2017年2月からは出勤日数を減らしたこともあり、学習のスピードは更に落ちていました。(家でも学習できたが、やる気になれなかった…)

それでもちまちま少しずつ読み進めることで、膨大に思えた「Ruby on Railsチュートリアル(第3版)」を終えることができるんだなぁ、としみじみ思います。

のんびり学習の間に第4版が出るし、のんびりすぎて最初の方忘れているしで学習の成果があるのかなんとも言えませんが
はじめる前よりはRuby on Railsのことが少しだけ分かったような気がします。

「Webアプリが作りたい!」とはじめた「1日20分のRailsチュートリアル」でしたが、
目的をそんなに意識しなかったからこそコツコツ続いたような気もします。
時間が来たらただやるだけ。

あと何でもいいから「アウトプット」を出すことも良かったような。
「誰かが見ているかも」なんて意識は正直持っていませんでしたが、学習する→アウトプットするの流れが自分に合っていたようです。

第4版を読んでみようかなー、とか、第12章のまとめで紹介されていた「Ruby on Railsを仕事にしていくための第一歩」を読んでみようかなー、と思ったりしますが、今後は未定です。

また「○○を学びたいー!」と思ったらここに書き流していこうと思います。
こんな自分の記録用ブログを読んで頂いて、スターを付けて頂いてありがとうございます!!!

それでは、また。

【186日目】【1日20分のRailsチュートリアル】【第12章】演習の2.

Ruby on Railsチュートリアル(第3版)

今日は「12.5 演習」の2.から。

12.5 演習

2.Homeページに表示されている1ページ目のフィードをテストしてください。リスト12.49はそのテンプレートです。
CGI.escapeHTMLでHTMLのエスケープ処理を使っている点に注目して、なぜこれが必要なのか考えてみてください。
(試しにエスケープ処理を外して、HTMLのソースコードを注意深く調べてください。マイクロポストの内容がおかしいはずです。)

フィードのテストってどうすればいいんだろうと思ってたら2個目がそうだったのか…!

テンプレートを参考に書いてみたけどこんな感じ…??

test/integration/following_test.rb

  test "feed on Home page" do
    get root_path
    @user.feed.paginate(page: 1).each do |micropost|
      assert_match CGI.escapeHTML(micropost.content), response.body
    end
  end

とりあえずテストは通りました。

$ bundle exec rake test
76 tests, 445 assertions, 0 failures, 0 errors, 0 skips

(試しにエスケープ処理を外して、HTMLのソースコードを注意深く調べてください。マイクロポストの内容がおかしいはずです。)

エスケープ処理を外したときに出てたエラーの中身の一部はこんな感じだったけど、これのこと…??

<span class=\"content\">\n    Writing a short test\n    \n  </span>

記号があるとエスケープ処理必要かな、って思ったけど記号なくても必要に見える。
演習1.のプロフィールのテストでは必要なかったのになんでなんだろう。。。フィードだから?

最後に疑問を残したままこれにて「Ruby on Railsチュートリアル(第3版)」終了です。
お疲れ様でした!

今日の学習時間は【19分】

【185日目】【1日20分のRailsチュートリアル】【第12章】演習の1.

Ruby on Railsチュートリアル(第3版)

今日は「12.5 演習」から。

12.5 演習

なお、演習とチュートリアル本編の食い違いを避ける方法については、演習用のトピックブランチに追加したメモ (3.6) を参考にしてください。

いつものように演習用のブランチ作りましょう。

$ git checkout following-users 
$ git checkout -b following-users-exercises

1. HomeページとProfileページにある統計情報のテストを書いてみてください。ヒント: リスト11.27のテストに追加してください。(Homeページの統計情報は別のテストにしてみませんか。)

「統計情報」って

  • ユーザー名
  • アイコン
  • フォロー数/フォローされている数
  • マイクロポスト(or フィード)

のことかな…??

Profileページの統計情報はすでにベースがあるのでそこにフォロー数/フォローされている数のテストを追加すればいいのかな。
マイクロポスト数のテストを参考に下記を追加。

test/integration/users_profile_test.rb

  test "profile display" do
    :
    assert_match @user.following.count.to_s, response.body
    assert_match @user.followers.count.to_s, response.body
    :
  end

テストは通りました。

$ bundle exec rake test
74 tests, 375 assertions, 0 failures, 0 errors, 0 skips

問題はHomeページの統計情報。
フィードってどうやってテストするんだ…!!!
てのが分からなかったのでまず他の情報についてテスト作りました。

test/integration/users_profile_test.rb

  test "home display" do
    log_in_as(@user)
    get root_path
    assert_template 'static_pages/home'
    assert_select 'h1', text: @user.name
    assert_select 'img.gravatar'
    assert_match @user.following.count.to_s, response.body
    assert_match @user.followers.count.to_s, response.body
    assert_match @user.feed.count.to_s, response.body
    assert_select 'div.pagination'
  end

ここまでは通りました。

$ bundle exec rake test
75 tests, 385 assertions, 0 failures, 0 errors, 0 skips

フィードに対するテスト書けてないけど今日はとりあえずここまで。
書き方思いつかない~

今日の学習時間は【36分】

次は「12.5 演習」の2.から。

【184日目】【1日20分のRailsチュートリアル】【第12章】第12章のまとめ

Ruby on Railsチュートリアル(第3版)

今日は「12.4 最後に」から。

12.4 最後に

ステータスフィードが追加され、Ruby on Railsチュートリアルのサンプルアプリケーションがとうとう完成しました。このサンプルアプリケーションには、Railsの主要な機能 (モデル、ビュー、コントローラ、テンプレート、パーシャル、フィルタ、検証、コールバック、has_many/belongs_to/has_many through関連付け、セキュリティ、テスティング、デプロイ) が多数含まれています。

これで完成したのか…!フォローもできるし、マイクロポストの投稿もできるもんね…!

12.4.2 読み物ガイド

(訳注: 日本語の読み物ガイドとしては、@zyunnosukeさんの記事「Ruby on Railsを仕事にしていくための第一歩」がよくまとまっています。「Railsチュートリアルを読み終わった後はどうすれば良い?」とお悩みの方は、是非ご参考にしてみてください。)

ほぅほぅ…!英語はしんどいから日本語サイトがいいよね…。

Railsガイド: トピック毎に分類された最新のRailsリファレンスです (訳注: RailsGuidesの日本語版を「Railsガイド」と呼んでいます)。

概念を理解するにはこれも良さそう。

12.4.2 本章のまとめ

・has_many :throughを使うと、複雑なデータ関係をモデリングできる
・has_manyメソッドには、クラス名や外部キーなど、いくつものオプションを渡すことができる
・適切なクラス名と外部キーと一緒にhas_many/has_many :throughを使うことで、能動的関係 (フォローする) や受動的関係 (フォローされる) がモデリングできた

このあたり難しいなぁ…。自力で組める気がしない。。。

Railsチュートリアル終わったらどうしようかなぁ、なんて考えてたけど、まだ演習あるので終わってから考えよう。
特に作りたいアプリケーションがあるわけじゃないんだよなー。

今日の学習時間は【21分】

次は「12.5 演習」から。

【183日目】【1日20分のRailsチュートリアル】【第12章】Homeページの表示を確認してGitにpushする

Ruby on Railsチュートリアル(第3版)

今日は「12.3.3 サブセレクト」のHomeページを確認するところから。

12.3.3 サブセレクト

思い出すキッカケとして、homeアクションはリスト12.48に再掲します。第11章ではただのプロトタイプでしたが (図11.14)、リスト12.46の実装によって、Homeページで完全なフィードが表示できていることがわかります (図12.23)。

Homeページに記載してたフィードのコードは修正しなくていいのか…!

サーバーを起動して

$ rails server -b $IP -p $PORT

Homeページにアクセス。

f:id:kt_zoe:20170926124041p:plain

おぉ、いい感じにフィードが表示されてる!

この時点で、masterブランチに変更を取り込む準備ができました。

これで最後なのか…!

$ bundle exec rake test
74 tests, 371 assertions, 0 failures, 0 errors, 0 skips
$ git add -A
$ git commit -m "Add user following"
$ git checkout master
$ git merge following-users

コードをリポジトリにpushして、本番環境にデプロイしてみましょう。

本番環境は今動いてないのでリポジトリにpushだけする。
本番環境もクレジットカード登録して動かしてみたいね。。。

$ git push
To git@bitbucket.org:kz-sue/sample_app.git
   ffb1018..0b1d296  master -> master

f:id:kt_zoe:20170926124054p:plain

今日の学習時間は【18分】

次は「12.4 最後に」から。いよいよ終わりかー!でもまだ演習があるぞ…!

【182日目】【1日20分のRailsチュートリアル】【第12章】SQLサブセレクトを使用する

Ruby on Railsチュートリアル(第3版)

今日は「12.3.3 サブセレクト」から。

12.3.3 サブセレクト

前節のヒントでおわかりのように、12.3.2のフィードの実装は、投稿されたマイクロポストの数が膨大になったときにうまくスケールアップできません。フォローしているユーザーが5000人程度になるとこういうことが起きる可能性があります。

あぁ、マイクロポストの読み込みというより、ユーザーの配列を作るのに大変なのか。

12.3.2で示したコードの問題は、following_idsでフォローしているすべてのユーザーをメモリーから一気に取り出し、フォローしているユーザーの完全な配列を作り出したことです。
(中略)
これを解決する方法は、フォローしているユーザーのidの検索をデータベースに保存するときにサブセレクト (subselect) を使用することです。

サブセレクト…???

[SQL] 7. サブクエリ 1 | TECHSCORE(テックスコア)

複数のクエリを組み合わせて、1つのクエリが生成した出力で、他のクエリの出力を制御することができます。少し分かりやすく言うと、クエリを入れ子にして、内側のクエリが値を生成し、それを外側のクエリの述語が評価して TRUE かどうか判断します。

どうもSQLの用語で「サブクエリ」とも言うっぽい。
複数のクエリを組み合わせることか…。

リスト12.45でコードを若干修正し、フィードをリファクタリングすることから始めましょう。

ちょっと変わった。

app/models/user.rb

  def feed
    Micropost.where("user_id IN (:following_ids) OR user_id = :user_id",
                    following_ids: following_ids, user_id: id)
  end

前者の疑問符を使用した文法も便利ですが、同じ変数を複数の場所に挿入したい場合は、後者の置き換え後の文法を使用するのがより便利です。

今は一箇所しか挿入してないけど、これから増やすのか。だからこっちのが便利なんだね。

このサブセレクトは、集合のロジックを (Railsではなく) データベースに保存するので、より効率が高まります。

へー…?そうなのか。なんかぱっと見変わってないんだけどこれで効率良くなるのか。

Rubyコード使うよりSQL使う方が効率いいってことなのかー。

app/models/user.rb

  def feed
    following_ids = "SELECT followed_id FROM relationships
                     WHERE  follower_id = :user_id"
    Micropost.where("user_id IN (#{following_ids})
                     OR user_id = :user_id", user_id: id)
  end

テストは特に問題なし。

$ bundle exec rake test
74 tests, 371 assertions, 0 failures, 0 errors, 0 skips

もちろん、サブセレクトを使用すればいくらでもスケールアップできるなどということはありません。大規模なWebサイトでは、バックグラウンドジョブを使用して、フィードを非同期で生成するなどの対策が必要でしょう。Webサイトのスケーリングのようなデリケートな問題は本書の範疇を超えます。

あ、その辺りは扱わないのか…。Twitterとかは非同期なのかもね。Ajax使ったりするサイトもありそう。
まぁこれは「チュートリアル」だからね。Webサイトって奥が深い。。

今日の学習時間は【21分】

次は「12.3.3 サブセレクト」のHomeページにフィードを追加するところから。

【181日目】【1日20分のRailsチュートリアル】【第12章】フィードを初めて実装する

Ruby on Railsチュートリアル(第3版)

今日は「12.3.2 フィードを初めて実装する」から。

12.3.2 フィードを初めて実装する

最初に、このフィードで必要なクエリについて考えましょう。ここで必要なのは、micropostsテーブルから、あるユーザー (つまり自分自身) がフォローしているユーザーに対応するidを持つマイクロポストをすべて選択 (select) することです。

SELECT * FROM microposts
WHERE user_id IN (<list of ids>) OR user_id = <user id>

そうですね。こうなりますね。

これらの条件から、フォローされているユーザーに対応するidの配列が必要であることがわかってきました。これを行う方法の1つは、Rubyのmapメソッドを使用することです。

検索のために配列を用意する、と。

実は、?を内挿すると自動的にこの辺りの面倒を見てくれます。さらに、データベースに依存する一部の非互換性まで解消してくれます。つまり、ここではfollowing_idsメソッドをそのまま使えばよいだけなのです。

なんか色々説明あったけどfollowing_idsを使うだけでいいらしい…!便利だな…

app/models/user.rb

  # ユーザーのステータスフィードを返す
  def feed
    Micropost.where("user_id IN (?) OR user_id = ?", following_ids, id)
  end

これだけでテスト通った!
結果だけ見ればすっきりしてるけど、ここに至るまでの過程も理解しておくと自分で作るとき参考になりそう。

$ bundle exec rake test
74 tests, 371 assertions, 0 failures, 0 errors, 0 skips

しかしリスト12.43にはまだ足りないものがあります。それが何なのか、次の節に進む前に考えてみてください(ヒント:フォローしているユーザーが5000人もいたらどうなるでしょうか)。

データベースからの読み込みにめっちゃ時間かかるね。アプリケーションの動き遅くなるね。多分ね。
ページング的な処理を入れるのかな…??

今日の学習時間は【15分】

次は「12.3.3 サブセレクト」から。