【第2章】Ruby on Rails チュートリアル 6.0(第6版)演習解説


はじめに

Rails初学者です。解説記事があまりなく、参考になればと思い書きました。
記載内容に間違いや、分かりづらい場合はコメントしていただけると幸いです。

Ruby on Rails チュートリアル 第2章

2.2.1

1.

CSSを知っている読者へ: 新しいユーザーを作成し、ブラウザのHTMLインスペクター機能を使って「User was successfully created.」の箇所を調べてみてください。ブラウザをリロードすると、その箇所はどうなるでしょうか?

右クリックをし検証を押してください。そうするとHTMLインスペクター機能を使用することができます。

1行目の<p id="notice"><%= notice %></p>に「User was successfully created.」が書かれています。

app/views/users/show.html.erb
<p id="notice"><%= notice %></p>

<p>
  <strong>Name:</strong>
  <%= @user.name %>
</p>

<p>
  <strong>Email:</strong>
  <%= @user.email %>
</p>

<%= link_to 'Edit', edit_user_path(@user) %> |
<%= link_to 'Back', users_path %>


ブラウザをリロードすると消えました。

2.

emailを入力せず、名前だけを入力しようとした場合、どうなるでしょうか?

エラーが出ず、作成することができました。

3.

「@example.com」のような間違ったメールアドレスを入力して更新しようとした場合、どうなるでしょうか?

エラーが出ず、作成することができました。

4.

上記の演習で作成したユーザーを削除してみてください。ユーザーを削除したとき、Railsはどんなメッセージを表示するでしょうか?

User was successfully destroyed.とメッセージが表示されました。

2.2.2

1.

図 2.11を参考にしながら、/users/1/edit というURLにアクセスしたときの振る舞いについて図を書いてみてください。

①ブラウザから「/users/1/edit 」というURLのリクエストをRailsサーバーに送信する。
②「/users/1/edit 」リクエストは、Usersコントローラ内のeditアクションに割り当てられる。
③editアクションが実行されるが、中身が無い

app/controllers/users_controller.rb
def edit
end

何も実行しないのでは?と思うかもしれません。
app/controllers/users_controller.rbの2行目に

app/controllers/users_controller.rb
before_action :set_user, only: [:show, :edit, :update, :destroy]

このようなコードが書かれています。
before_actionを記述すると、newやcreate、editといったアクションを実行する前に、何かしらの処理を実行できます。
今回は、set_userを実行します。
中身を見ましょう。

/app/controllers/users_controller.rb
private
  # Use callbacks to share common setup or constraints between actions.
  def set_user
    @user = User.find(params[:id])
  end

@user = User.find(params[:id])で、user:idを取得します。
ということで、③は
User.find(params[:id])

⑥Usersコントローラは、ユーザーのidを@user変数に保存し、editビューに渡す。

2.

図示した振る舞いを見ながら、Scaffoldで生成されたコードの中でデータベースからユーザー情報を取得しているコードを探してみてください。Hint: set_userという特殊な場所の中にあります。

1番③と同じです。

app/controllers/users_controller.rb



private
  # Use callbacks to share common setup or constraints between actions.
  def set_user
    @user = User.find(params[:id])
  end

3.

ユーザーの情報を編集するページのファイル名は何でしょうか?

1番⑥と同じです。
[app/views/users/edit.html.erb]

2.3.1

1.

CSSを知っている読者へ: 新しいマイクロポストを作成し、ブラウザのHTMLインスペクター機能を使って「Micropost was successfully created.」の箇所を調べてみてください。ブラウザをリロードすると、その箇所はどうなるでしょうか?


ブラウザをリロードすると表示が消えました。

2.

マイクロポストの作成画面で、ContentもUserも空にして作成しようとするどうなるでしょうか?

作成することができました。

3.

141文字以上の文字列をContentに入力した状態で、マイクロポストを作成しようとするとどうなるでしょうか?(ヒント: WikipediaのRubyの記事にある設計思想の引用文が140文字を超えているので、これをコピペしてみましょう)

140字を超えても作成することができました。

4.

上記の演習で作成したマイクロポストを削除してみましょう。

「Micropost was successfully destroyed.」と表示され、削除ができました。

2.3.2

1.

先ほど2.3.1.1の演習でやったように、もう一度Contentに141文字以上を入力してみましょう。どのように振る舞いが変わったでしょうか?

validatesを追加したことにより、エラーが表示されました。

2.

CSSを知っている読者へ: ブラウザのHTMLインスペクター機能を使って、表示されたエラーメッセージを調べてみてください。

「Content is too long (maximum is 140 characters)」コンテンツが長すぎます(最大140文字)と怒られました。

2.3.3

1.

ユーザーのshowページを編集し、ユーザーの最初のマイクロポストを表示してみましょう。同ファイル内の他のコードから文法を推測してみてください(コラム 1.2で紹介した技術の出番です)。うまく表示できたかどうか、/users/1 にアクセスして確認してみましょう。

first_userはインスタンス変数の@userに置き換えます。
before_actionでset_userアクションが実行されます。
before_actionとは、newやcreate、editといったアクションを実行する前に、何かしらの処理を実行するものです。
set_userアクションの中身はこのようになっています。

app/controllers/users_controller.rb
private
  # Use callbacks to share common setup or constraints between actions.
  def set_user
    @user = User.find(params[:id])
  end

first_user = User.first@user = User.find(params[:id])
に置き換わります。

コンソール
$ rails console
> first_user = User.first
  -->下に置き換わる
  -->@user = User.find(params[:id])

first_user.microposts@user.micropostsになります。

コンソール
> first_user.microposts
  -->下に置き換わる
  -->@user.microposts

@user.microposts.first

赤枠のレコードを取得できます。
@user.microposts.first.contentと書くとcontentのみ取得できます。

app/views/users/show.html.erb
<p id="notice"><%= notice %></p>

<p>
  <strong>Name:</strong>
  <%= @user.name %>
</p>

<p>
  <strong>Email:</strong>
  <%= @user.email %>
</p>

<!--ここから-->
<p>
  <strong>Content:</strong>
  <%= @user.microposts.first.content%>
</p>
<!--ここまで追加-->

<%= link_to 'Edit', edit_user_path(@user) %> |
<%= link_to 'Back', users_path %>

2.

リスト 2.18は、マイクロポストのContentが存在しているかどうかを検証するバリデーションです。マイクロポストが空でないことを検証できているかどうか、実際に試してみましょう(図 2.17のようになっていると成功です)。

presenceメソッドとは、presenceメソッドを使用したオブジェクトが存在すればそのオブジェクト自身を返し、存在しなければnilを返すメソッドです。
今回はmicropostのcontentが空の場合nillを返し、エラーが出ます。

app/models/micropost.rb
class Micropost < ApplicationRecord
  belongs_to :user
  validates :content, length: { maximum: 140 },
                      presence: true
end

3.

リスト 2.19のFILL_INとなっている箇所を書き換えて、Userモデルのnameとemailが存在していることを検証してみてください(図 2.18)。

app/models/micropost.rbを参考にして書きます。今回は存在していることを検証するので、presenceメソッドのみを使用します。

app/models/user.rb
class User < ApplicationRecord
  has_many :microposts
  validates :name, presence: true    
  validates :email, presence: true    
end

2.3.4

1.

Applicationコントローラのファイルを開き、ApplicationControllerがActionController::Baseを継承している部分のコードを探してみてください。

app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  def hello
    render html: "hello, world!"
  end
end

2.

ApplicationRecordがActiveRecord::Baseを継承しているコードはどこにあるでしょうか? 先ほどの演習を参考に、探してみてください。ヒント: コントローラと本質的には同じ仕組みなので、app/modelsディレクトリ内にあるファイルを調べてみると...?)

app/models/application_record.rb
class ApplicationRecord < ActiveRecord::Base
  self.abstract_class = true
end

2.3.5

1.

本番環境で2〜3人のユーザーを作成してみましょう。

2.

本番環境で最初のユーザーのマイクロポストを作ってみましょう

3.

マイクロポストのContentに141文字以上を入力した状態で、マイクロポストを作成してみましょう。リスト 2.14で加えたバリデーションが本番環境でもうまく動くかどうか、確認してみてください。

動作確認のため省略