各投稿者が「誰がその投稿をしたか」という情報を持っている必要
postテーブルにuser_idカラムを追加する
rails g migration
を用いる。
add_user_id_to_posts
というファイル名のマイグレーションファイルを作成します。
rails g migration add_user_id_to_posts
マイグレーションファイルを作成する。
class AddUserIdToPosts < ActiveRecord::Migration[5.0]
def change
add_column :posts, :user_id, :integer
end
end
マイグレーションファイルの中身を編集する
postsテーブルにuser_idカラム(整数型)を追加する
rails db:migrate
マイグレーションファイルを編集した後はこれをやる。
バリデーションを行う。
class Post < ApplicationRecord
validates :content, {presence: true, length: {maximum: 140}}
validates :user_id, {presence: true}
end
新規投稿をログインユーザーに紐付けよう
誰が投稿したのかがわかるようになった。
ログインしているユーザーが投稿する
def create
@post = Post.new(
content: params[:content],
# user_idの値をログインしているユーザーのidにしてください
user_id: @current_user.id
)
これで作成されるときにログイン中のユーザーのidが入るのかな。
成功。
投稿にユーザー情報を表示しよう
投稿の詳細ページにユーザー画像と名前を表示させる。
user_idカラムから情報を取ってくる。
user_idカラムの値から、そのユーザーの情報を取得する必要があります。
showコントローラでインスタンス変数に代入させる。
def show
@post = Post.find_by(id: params[:id])
# 変数@userを定義してください
@user = User.find_by(id: @post.user_id)
end
これでuser_idを基にUserのデータを引っ張ってくる。
SyntaxError in PostsController#show
app/views/posts/show.html.erb:11: syntax error
解決
<% link_to("#{@user.name}", "/users/#{@user.id}")
<% link_to("#{@user.name}", "/users/#{@user.id}") %>
%>
で閉じていなかったためだ。
imgタグのsrcの値は、「<%= "/user_images/#{@user.image_name}" %>」としてください
publicファイルから画像のデータを取り出さなくてはいかないから/user_images/
から書かなくてはならない。
<img src="<%= "/user_images/@user.image_name" %>">
あとブラウザに表示させるために<%= %>
をつけなくてはならない。
<img src="<%= "/user_images/#{@user.image_name}" %>">
埋め込みrubyを使うため#{}で囲まなければ値が表示されない。
インスタンス変数を使ったリンクの書き方
<%= link_to( @user.name, "/users/#{@user.id}") %>
リンクに表示させる文字列にインスタンス変数を使う場合は埋め込みrubyは使わない。
ブラウザに表示させるときは<%= %>
を使う。
インスタンスメソッドを定義しよう
Postモデル内で定義したインスタンスメソッドは、右の図のようにpostインスタンスに対して用いることができます。
モデル内でメソッドを作成することができる。そのモデルのインスタンスに用いることができる。
Postモデル内にその投稿に紐付いたuserインスタンスを戻り値として返すuserメソッドを定義しましょう。
class Post < ApplicationRecord
.
.
.
# インスタンスメソッドuserを定義してください
def user
return User.find_by(id: self.user_id)
end
end
self
はインスタンスメソッド内でそのインスタンス自信を表す。
この場合はpostモデルを表す。
[1] pry(main)> post = Post.find_by(id: 1)
Post Load (0.1ms) SELECT "posts".* FROM "posts" WHERE "posts"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]]
=> #<Post:0x000056459798d6f8
id: 1,
content: "hogehoge\r\n",
created_at: Mon, 16 May 2022 14:25:03 JST +09:00,
updated_at: Mon, 16 May 2022 14:25:03 JST +09:00,
user_id: 1>
[2] pry(main)> post.user
User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]]
=> #<User:0x00005645978be808
id: 1,
name: "にんじゃわんこ",
email: "wanko@prog-8.com",
created_at: Tue, 18 Apr 2017 17:06:52 JST +09:00,
updated_at: Tue, 18 Apr 2017 17:06:52 JST +09:00,
image_name: "default_user.jpg",
password: "ninjawanko">
変数post(Postモデル)がインスタンスメソッドuserを使うことによってUserモデルの情報を取り出すことができるのか。
思ったこと
紐付けをしてあるとモデル同士を跨ぐことができるのか。
インスタンスメソッドを用いる
@user
に@post
を用いてUserインスタンスを取り出す
@user = User.find_by(id: @post.user_id)
インスタンス変数を用いる
@user = @post.user
思ったこと
インスタンスメソッドを使うことによって見た目が簡単になった。