いいね機能の作成
TwitterやInstagramなどのSNSには「いいね」という機能があります。
この機能を実際にRailsで実装してみます。
見出し
- 「いいね」とは
- ユーザー認証機能の実装
- 投稿機能の実装
- いいね機能の実装
- 完成コード
1. 「いいね」とは
いいねとは何でしょうか?
アプリケーションにはユーザーと投稿が存在していることを前提とします。
具体的にはユーザーテーブルと投稿のテーブルが存在していることとなります。
ユーザーが3人いてそれぞれIDが1, 2, 3、投稿も三つありIDが1, 2, 3とします。
いいねとはユーザーと投稿のIDがセットになっている状態のことを指します。
例えば、ユーザーIDが1, 投稿IDが1がセットになっていればID1のユーザーが投稿1をいいねしている状態となります。
「いいね」は概念でしかないため、他のアプリケーションでは「一時保存」や「あとで見る」、「キープ」など言い換えている場合があります。

こちらの画像ではユーザー1が投稿1, 2、ユーザー3が投稿1をいいねしているという状態を表しています。
2. ユーザー認証機能の作成
ユーザーがいなければいいねはできませんので、ユーザー認証機能を作成していきます。
まずは、アプリケーションの基盤を作成し、その後ユーザー認証機能を作成します。
ユーザー認証機能は下記リンクを参考にして作成しても良いです。
$ rails new sample_app
$ cd sample_app
...追加
gem 'devise'
$ bundle
$ rails g devise:install
$ rails g devise User
$ rails db:migrate
トップページを作成します。
$ rails g controller home top
...編集
get 'home/top'
↓
root 'home#top'
...編集
<body>
<% if user_signed_in? %>
<%= link_to 'ログアウト', destroy_user_session_path, method: :delete %>
<% else %>
<%= link_to 'ログイン', new_user_session_path %>
<%= link_to '新規登録', new_user_registration_path %>
<% end %>
<%= yield %>
</body>
これで新規登録・ログイン・ログアウトができるようになりました。
http://localhost:3000にアクセスして試してみましょう。
3. 投稿機能の実装
次に投稿機能を作成します。
こちらを一つ一つ説明すると長くなるため、下記記事を参考にして進めていきます。
Scaffoldを導入していきます。
$ rails g scaffold post title:string user_id:integer
$ rails db:migrate
...追加
<%= link_to '投稿一覧', posts_path %>
ログインしているユーザーしか投稿関連を行えないように、
posts_controller.rbの3行目あたりに以下を追加します。
...追加
before_action :authenticate_user!
投稿とユーザーを紐づけていきます。
...追加
belongs_to :user
...追加
has_many :posts
Scaffoldで作成するとuser_idのフォームが作成されてしまうため、
_form.html.erbの下記を削除します。
<div class="field">
<%= form.label :user_id %>
<%= form.number_field :user_id %>
</div>
また、ストロングパラメータからもuser_idを削除します。
...編集
params.require(:post).permit(:title)
投稿作成時にログインしているユーザーのidを格納する様にします。
...編集
def create
@post = Post.new(post_params)
@post.user_id = current_user.id
ここまでで、ユーザー認証機能と投稿機能を作成することはできました。
4. いいね機能の実装
まずはユーザーIDと投稿IDを格納するためのモデルを作成します。
$ rails g model Favorite user_id:integer post_id:integer
$ rails db:migrate
userモデル, postモデル, favoriteモデルそれぞれに関連付けをしていきます。
...追加
has_many :favorites
...追加
has_many :favorites
...追加
belongs_to :user
belongs_to :post
また、ユーザーがいいねしている投稿を取得できるように
モデルでthroughオプションを利用した関連付けを行います。
...追加
has_many :favorite_posts, through: :favorites
そして、いいねしているかを投稿の右側に表示させます。
まずはいいねしているかどうかを確かめる関数をuser.rbに記載します。
...追加
def favorited_by?(post_id)
favorites.where(post_id: post_id).exists?
end
...編集
<td><%= post.title %></td>
<% if current_user.favorited_by?(post.id) %>
<td>いいね外す</td>
<% else %>
<td>いいねする</td>
<% end %>
<td><%= link_to 'Show', post %></td>
<td><%= link_to 'Edit', edit_post_path(post) %></td>
<td><%= link_to 'Destroy', post, method: :delete, data: { confirm: 'Are you sure?' } %></td>
次に、いいねを実際したり外したりできるようにします。
$ rails g controller favorites
...追加
def create
Favorite.create(user_id: current_user.id, post_id: params[:id])
redirect_to posts_path
end
def destroy
Favorite.find_by(user_id: current_user.id, post_id: params[:id]).destroy
redirect_to posts_path
end
ルーティングを設定します。
...追加
post 'favorite/:id' => 'favorites#create', as: 'create_favorite'
delete 'favorite/:id' => 'favorites#destroy', as: 'destroy_favorite'
ビューを編集します。
<td><%= post.title %></td>
<% if current_user.favorited_by?(post.id) %>
<td><%= link_to 'いいね外す', destroy_favorite_path(post), method: :DELETE %></td>
<% else %>
<td><%= link_to 'いいねする', create_favorite_path(post), method: :POST %></td>
<% end %>
<td><%= link_to 'Show', post %></td>
<td><%= link_to 'Edit', edit_post_path(post) %></td>
<td><%= link_to 'Destroy', post, method: :delete, data: { confirm: 'Are you sure?' } %></td>
ここまででいいね機能を作成することができました。
次回はいいね数を取得できるようにしていきます。