25
29

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Railsで「いいね」機能を実装

Posted at

GWに入ってからRailsで新しくアプリを作ってます。
今回は「いいね」機能を実装するにあたって自分の中できちんと整理すべくメモ。

参考にした記事

今回も沢山の方々の記事を参考にさせていただきました。ありがとうございます。
【Rails】Twitterのいいね機能を非同期で実装する方法【Ajax】
Railsで remote: true と js.erbを使って簡単にAjax(非同期通信)を実装しよう!(いいね機能のデモ付)
[Rails]いいね機能の非同期での実装!!!

Likeモデル

今作っているのはユーザー(User)が食べ物(Food)に「いいね」できるという機能をつける、ということで両者を紐付ける役割としてLikeモデルを作ります。

rails g model like user_id:integer food_id:integer

UserとLikeは1対多、FoodとLikeも1対多なので、

app/model/user.rb
has_many :likes
app/model/food.rb
has_many :likes
app/model/like.rb
belongs_to :user
belongs_to :food

とします。

ルーティング

config/routes.rbに下記のように追記します。

config/routes.rb
post "likes/:food_id/create", to: "likes#create", constraints: {food_id: /\d+/}, as: :likes_create
post "likes/:food_id/delete", to: "likes#delete", constraints: {food_id: /\d+/}, as: :likes_delete

コントローラー

コントローラーも作成します。

rails g controller likes

設定したルーティングで呼び出すアクションをapp/controllers/likes_controller.rbに書きます。

app/controllers/likes_controller.rb
def create
  @like = Like.new(user_id: @current_user.id, food_id: params[:food_id])
  @like.save
  @food = Food.find_by(id: @like.food_id)
  @like_count = Like.where(food_id: params[:food_id]).count
end

def delete
  @like = Like.find_by(user_id: @current_user.id, food_id: params[:food_id])
  @food = Food.find_by(id: @like.food_id)
  @like.destroy
  @like_count = Like.where(food_id: params[:food_id]).count
end

また、カウントの数字を表示するための一文をボタンを設置するビューのファイルにも書いておきます。

@like_count = Like.where(food_id: params[:food_id]).count

部分テンプレート

今回は「いいね」ボタンを表示する部分テンプレートを作成して、ボタンを設置したいところに挿入するという形を取りました。
部分テンプレートのファイル名は_(アンダーバー)で始める必要があります。

app/views/likes/_like.html.erb
<div class="like_button_on">
	<%= link_to "いいね済み", likes_delete_path(food_id: @food.id), {method: "post", remote: true} %>
	<%= @like_count %>
</div>
<div class="like_button">
	<%= link_to "いいね", likes_create_path(food_id: @food.id), {method: "post", remote: true} %>
	<%= @like_count %>
</div>

「remote: true」とすることでjs形式で送ることができます。これにより次に書く非同期での処理ができるようになります。

非同期処理

「いいね」ボタンを押すとボタンの色が変わり、カウントの数字も変わる仕様にするための処理を書いていきます。

app/views/likes/create.js.erb
$('.buttons_<%= @food.id %>').html("<%= j(render partial: 'likes/like' ) %>");
app/views/likes/delete.js.erb
$('.buttons_<%= @food.id %>').html("<%= j(render partial: 'likes/like' ) %>");

コントローラーで指定したアクションと同じ名前で.js.erbファイルを作ります。
こうすることでアクションが実行されるとこちらのファイルを読み込み、ボタンを押した箇所が再びレンダリングされます。

部分テンプレートの挿入

あとはボタンを設置したいところに、

<div class="buttons_<%= @food.id %>"><%= render partial: 'likes/like' %></div>

と書けばOKです。
ボタンを押すと「いいね」の作成・削除が行われ、その都度指定したdivの中身が書き換えられます。

CSS

.like_button{
	background-color: #BDBDBD;
}

.like_button_on{
	background-color: #FE2E2E;
}

と指定してあげると押すたびにボタンの色が灰色⇔赤色と変わります。色はお好みでどうぞ。

最後に

実際に作ってみるまで部分テンプレートの使い方や仕組み等を全然理解できていませんでしたが、ほんの少しだけ理解が深まったような気がします。
まだまだ理解できていないことが多いので、今後も手を動かしながら実践していきたいと思います。
毎度のことながら、間違っている箇所等あればご指摘いただければ幸いです。

25
29
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
25
29

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?