Closed5

【Railsチュートリアル】「2.3.3 ユーザーはたくさんマイクロポストを持っている」の演習へのアプローチ記録

MASAMASA

目的

ユーザーのshowページを編集し、ユーザーの最初のマイクロポストを表示する。

MASAMASA

views/users/show.html.erbを編集

まず、views/microposts/show.html.erbの内容を確認すると、下記コードでポスト内容を表示している。

views/microposts/show.html.erb
<p>
  <strong>Content:</strong>
  <%= @micropost.content %>
</p>

なので、views/users/show.html.erbにそれを追記する。

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>First_Content:</strong>
  <%= @micropost.content %>
</p>


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

そして、ブラウザ更新。

undefined method content' for nil:NilClass」というエラーメッセージが表示される。 ビューapp/views/users/show.html.erbはコントローラapp/controllers/users_controller.rbから呼ばれている。 usersコントローラにはインスタンス変数@contentは定義されていないので、先ほどのエラーになったのかと納得。 では、どうすればいいのか。インスタンス変数@userを利用して、@user.content`のようにデータ指定すればよいのではないかと考えられるので、それをどうすれば実現できるかを考える。

MASAMASA

@user.contentでデータ表示できないかを考える。

@user.contentを使えるようにするには、まず、@userに登録されているデータを調べることから始める。
データベースとのやりとりは、モデルapp/models/user.rbが行っているので、それを確認。

app/models/user.rb
class User < ApplicationRecord
  has_many :microposts
end

と、このファイルを確認したことで、この演習の前のステップで、has_many :micropostsを記述し、異なるデータモデル同士の関連付けを行っていたことを思い出した。
これを利用してこの演習をするのだなと思い、再び、チュートリアルの記述を確認。

すると、micropost = first_user.microposts.firstで最初のユーザーの最初のポスト内容をもってくるとあるので、これを使えないか考える。
app/controllers/users_controller.rbを確認すると、

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にはユーザーIDが入っているとわかる。
ということは、micropost = first_user.microposts.first@user.micropost.firstとすることで、該当ユーザーの最初のポスト内容が取得できるはずなので、app/views/microposts/show.html.erbをそのように編集する。

MASAMASA

app/views/microposts/show.html.erbの編集

app/views/users/show.html.erb@user.micropost.firstを記載。

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>First_Content:</strong>
  <%= @user.microposts.first %>
</p>


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

そして、ブラウザを更新。

うまくデータを取得できていないようだ。。

一旦。コマンド"docker-compose run --rm web exec rais c"でコンソールを開き、テーブルの中身を確認する。

masa@DESKTOP-0CNPS43:~/RailsTutorial$ docker-compose run --rm web bundle exec rails c
Creating railstutorial_web_run ... done
Loading development environment (Rails 6.1.0)
irb(main):001:0> User.all
  User Load (0.2ms)  SELECT "users".* FROM "users" /* loading for inspect */ LIMIT $1  [["LIMIT", 11]]
=> #<ActiveRecord::Relation [
#<User id: 1, name: "masa", email: "masaa@gmail.com", created_at: "2021-01-04 22:16:17.756753000 +0000", updated_at: "2021-01-04 22:18:08.383711000 +0000">, 
#<User id: 5, name: "aiku", email: "aiku@gmail.com", created_at: "2021-01-05 04:46:12.228101000 +0000", updated_at: "2021-01-05 04:46:12.228101000 +0000">, 
#<User id: 6, name: "syanon", email: "syanon@nikoniko.com", created_at: "2021-01-05 04:49:40.646040000 +0000", updated_at: "2021-01-05 04:49:40.646040000 +0000">]>
irb(main):002:0> 
irb(main):003:0> Micropost.all
  Micropost Load (0.4ms)  SELECT "microposts".* FROM "microposts" /* loading for inspect */ LIMIT $1  [["LIMIT", 11]]
=> #<ActiveRecord::Relation [
#<Micropost id: 1, content: "goodmornig", user_id: 1, created_at: "2021-01-05 00:43:15.463431000 +0000", updated_at: "2021-01-05 00:43:15.463431000 +0000">, 
#<Micropost id: 3, content: "a", user_id: 1, created_at: "2021-01-05 00:44:37.269892000 +0000", updated_at: "2021-01-05 00:44:37.269892000 +0000">, 
#<Micropost id: 8, content: "aiku", user_id: 5, created_at: "2021-01-05 04:52:41.125643000 +0000", updated_at: "2021-01-05 04:52:41.125643000 +0000">, 
#<Micropost id: 9, content: "syanon", user_id: 6, created_at: "2021-01-05 04:52:53.550736000 +0000", updated_at: "2021-01-05 04:52:53.550736000 +0000">]>

データをみると、登録データは問題なさそう。
コンソール上で@user.microposts.firstを確認する。

MASAMASA

コンソール上で"@user.microposts.first"を確認する。

@userをコンソールでつかえるように翻訳しないといけないが、一旦"Micropost.first"を確認。

irb(main):010:0> Micropost.first
  Micropost Load (0.3ms)  SELECT "microposts".* FROM "microposts" ORDER BY "microposts"."id" ASC LIMIT $1  [["LIMIT", 1]]
=> #<Micropost id: 1, content: "goodmornig", user_id: 1, created_at: "2021-01-05 00:43:15.463431000 +0000", updated_at: "2021-01-05 00:43:15.463431000 +0000">

これだと、user_id = 1のカラムが抜き出されている。
ということは、さらに、contentの中身が取得できるようにするには、Micropost.first.contentとすればよいのではないか。

irb(main):011:0> Micropost.first.content
  Micropost Load (0.4ms)  SELECT "microposts".* FROM "microposts" ORDER BY "microposts"."id" ASC LIMIT $1  [["LIMIT", 1]]
=> "goodmornig"

goodmoningキタ━━━━(゚∀゚)━━━━!!
これをapp/views/users/show.html.erbに反映させる。

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>First_Content:</strong>
  <%= @user.microposts.first.content %>
</p>

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

ブラウザを更新した結果、、、

goodmoningキタ━━━━(゚∀゚)━━━━!!

~fin~

このスクラップは2021/01/05にクローズされました