#経緯
現在ポートフォリオ用に「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を記述します。
has_many :posts, dependent: :destroy, foreign_key: :post_user_id
投稿は複数あるので複数系にしてください。
ちなみにdependent: :destroyはユーザーが削除されたら自動的に投稿も削除されるという優秀な機能です。
##belongs_to
次は一対多の一の方、ユーザーの紐付けです。
belongs_to:user
def user
return User.find_by(id: self.user_id)
end
一の方はbelongs_toで紐付けられます。
また、userメソッドをモデルで定義しておけば汎用性が高くなるので書いときます。
#Controllerの設定
私はuser_showというページで該当ユーザーの投稿一覧を表示したかったので、コントローラーに以下のように記述しました。
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文で回してあげれば一覧が確認できます。
<% @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>投稿者  </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を勉強したら結構スッと入ってこれました。
イメージって大事ですね。
もしこの記事が誰かの助けになれたら幸いです。
ではでは。