Rails いいね機能
いいね機能
「いいね機能」のテーブルを設計
カラム名 | データ型 | カラムの説明 |
---|---|---|
id | integer | 「いいね」ごとのID |
user_id | integer | 「いいね」したユーザのID |
post_image_id | integer | 「いいね」された投稿画像のID |
Model
「Favorite」という名でモデルを作成
ターミナル
rails g model Favorite user_id:integer post_image_id:integer
マイグレーションでテーブルをデータベースへ反映
rails db:migrate
Favoriteモデルのカラムに関連付け
app/models/favorite.rb
belongs_to :user
belongs_to :post_image
PostImageモデルに関連付け
app/models/post_image.rb
has_many :favorites, dependent: :destroy
:
def favorited_by?(user)
favorites.exists?(user_id: user.id)
end
favorited_by?メソッド
このメソッドで、引数で渡されたユーザidがFavoritesテーブル内に存在(exists?)するかどうかを調べられる!
存在していればtrue、存在していなければfalseを返す。
Userモデルに関連付け
has_many :favorites, dependent: :destroy
Routing
config/routes.rb
resources :post_images, only: [:new, :create, :index, :show, :destroy] do
resource :favorites, only: [:create, :destroy]
end
resourceとなっている点
単数形にすると、/:idがURLに含まれなくなる。
コメント機能では「1人のユーザが1つの投稿に対して何度でもコメントできる」という仕様だったため、destroyをする際にidを受け渡して「どのコメントを削除するのか」を指定する必要があった。
いいね機能の場合は「1人のユーザーは1つの投稿に対して1回しかいいねできない」という仕様であるため、destroyをする際にもユーザーidと投稿(post_image)idが分かれば、どのいいねを削除すればいいのかが特定できる。
そのため、URLに/:idを含めない形にしている!!
resourceは「それ自身のidが分からなくても、関連する他のモデルのidから特定できる」といった場合に用いることが多い
実際にURLを確認
rails routes
favorites関連のルーティングが作成された!
post_image_favorites DELETE /post_images/:post_image_id/favorites(.:format) favorites#destroy
POST /post_images/:post_image_id/favorites(.:format) favorites#create
Controller
いいね機能のコントローラを作成
いいね機能では他のモデルにあるような詳細ページや一覧ページなどのViewが必要ないため
今回はアクションを指定せずにコントローラを作成。
rails g controller favorites
いいね機能も、indexアクションやnewアクションは作成しない。
app/controllers/favorites_controller.rb
def create
end
def destroy
end
end
createアクションとdestroyアクションの中身を実装
app/controllers/favortes_controller.rb
def create
post_image = PostImage.find(params[:post_image_id])
favorite = current_user.favorites.new(post_image_id: post_image.id)
favorite.save
redirect_to post_image_path(post_image)
end
def destroy
post_image = PostImage.find(params[:post_image_id])
favorite = current_user.favorites.find_by(post_image_id: post_image.id)
favorite.destroy
redirect_to post_image_path(post_image)
end
View
app/views/post_images/show.html.erb
<% if @post_image.favorited_by?(current_user) %>
<p>
<%= link_to post_image_favorites_path(@post_image), method: :delete do %>
♥<%= @post_image.favorites.count %> いいね
<% end %>
</p>
<% else %>
<p>
<%= link_to post_image_favorites_path(@post_image), method: :post do %>
♡<%= @post_image.favorites.count %> いいね
<% end %>
</p>
<% end %>
投稿画像に付けられた「いいね」に、自分(ログインしているユーザ)が含まれているかをfavorited_by?メソッドで判定している。
「含まれるとき/含まれないとき」で、表示と機能を分け、リンクのaタグのメソッドを、条件によって変えている。
確認
実際に「いいね」を押して確かめる!
応用編
いいねのハートに色をつける方法
View
<% if book.favorited_by?(current_user) %>
<%= link_to book_favorites_path(book), method: :delete do %>
<i class="fas fa-heart" aria-hidden="true" style="color: red;"></i>
<%= book.favorites.count %> いいね
<% end %>
<% else %>
<%= link_to book_favorites_path(book), method: :post do %>
<i class="fas fa-heart" aria-hidden="true"></i>
<%= book.favorites.count %> いいね
<% end %>
<% end %>
ちなみにこれも学んだ!
前のページにリダイレクトする方法
redirect_to request.referer
ユーザーが直前にアクセスしたページにリダイレクトするために使用される!!
柔軟性の高いページ遷移を実現することができる🙆🏻♀️
いいね機能の復習!!
今日はここまで!
Discussion