Help us understand the problem. What is going on with this article?

【Rails】投稿とユーザーの紐付け(一対多)のメモ

経緯

現在ポートフォリオ用に「book memory phrase」というアプリを作っています。
自分が印象に残ったフレーズを引用した書籍とともに紹介して本との出会いを作る場です。

そこでユーザーと投稿の紐付けを行って、誰がどの投稿をしたか一覧で見れるような機能を実装したのですが、has_manyやbelongs_toなど学ぶことが多かったのでアウトプットしとこうと思います。

投稿したユーザーid

まずはデータベース上のidを紐付ける必要があります。

今回の場合だと、UserテーブルのidをPostテーブルに突っ込んで、誰の投稿かわかるようにします。

最初からこの機能は実装する気でいたので、Postテーブルを作る時点でidカラムとは別にuser_idカラムを作り、投稿する際にユーザーのidを突っ込めるようにしてました。

その辺については以前書いた【Rails】railsブログサイトの練習で躓いたところメモにも載せていますのでそちらを参考にしてもらえたらと思います。

Modelの設定

idが突っ込めたら次は紐付けです。これはModelで設定します。

has_many

has_manyは一対多の多の方です。
ユーザー1に対して投稿は多数あるので、ユーザーモデルにhas_manyを記述します。

user.rb
has_many :posts, dependent: :destroy, foreign_key: :post_user_id

投稿は複数あるので複数系にしてください。

ちなみにdependent: :destroyはユーザーが削除されたら自動的に投稿も削除されるという優秀な機能です。

belongs_to

次は一対多の一の方、ユーザーの紐付けです。

post.rb
belongs_to:user

def user
   return User.find_by(id: self.user_id)
end

一の方はbelongs_toで紐付けられます。
また、userメソッドをモデルで定義しておけば汎用性が高くなるので書いときます。

Controllerの設定

私はuser_showというページで該当ユーザーの投稿一覧を表示したかったので、コントローラーに以下のように記述しました。

home_controller.rb
before_action :set_post, only[:user_show, :edit, :update, :destroy]

#省略

#@userにモデルで定義したuserメソッドを@post.userで代入
#@postsに@userの投稿を全て代入
def user_show
   @user = @post.user
   @posts = @user.posts
end

#省略

private
#Post.find_by(id: params[:id])はよく使うので定義しといてbefore_actionで反映。
def set_post
   @post = Post.find_by(id: params[:id])
end

これでコントローラーの準備は整いました。

Viewの設定

コントローラーで作った@postsをeach文で回してあげれば一覧が確認できます。

user_show.html.erb
<% @posts.each do |post| %>
   <div class="book-img col-lg-4 col-md-6 col-sm-12 center-block mx-auto">
      <div class="box">
         <div class="image-box">
            <h5><%= post.phrase %></h5>
            <p class="name">
               <span>投稿者&ensp;&ensp;</span><%= link_to("#{post.post_user}", "/home/#{post.id}/user_show")%>
            </p>
            <img src='<%= post.book_image %>' class="img-fluid d-block">
         </div>
         <div>
            <p class="title">
               『<%= post.title %>』
            </p>
            <p class="author">
               著者 <%= post.author %>
            </p>
            <p>★ おすすめポイント</p>
            <p class="content">
               <%= post.content%>
               <% if user_signed_in? && current_user.id == post.user_id %>
                  <span class="edit-delete">
                  <%=link_to("編集" , "/home/#{post.id}/edit",class:"text-muted") %>
                  <%=link_to("削除" , "/home/#{post.id}/destroy",method: :post,class:"text-muted") %>
                  </span>
               <% end %>
            </p>
         </div>
      </div>
   </div>
<% end %>

まとめ

投稿の紐付けは必須機能ですが、結構躓くところでもあると思います。

かく言う私も何度も躓いたのですがSQLを勉強したら結構スッと入ってこれました。
イメージって大事ですね。

もしこの記事が誰かの助けになれたら幸いです。
ではでは。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした