ああ
みなさん、こんにちは!
筆者は大学生限定のプログラミングスクール「GeekSalon」でメンターをしています!
興味のある方や話だけでも聞いてみてい方はぜひのぞいてみてください👍
さっそく今回の本題に入っていきます!
今回は投稿に対するいいねを、ページ遷移せずともできる/取り消せるようにしていきたいと思います。
なお、いいね機能は実装済みという前提で話を進めていくため、いいね機能をまだ実装していない人は先にそちらの実装をお願いします。
また今回の実装では部分テンプレートを用いています。部分テンプレートについての理解が怪しい方は、参考となる記事を載せておきますので、そちらも参照してください!
##実装環境
ruby 2.7.4p191 (2021-07-07 revision a21a3b7d23) [x64-mingw32]
Rails 6.1.4.1
(※投稿機能、投稿に対するいいね機能は実装済みという前提で記事を書いていきます。)
##実装① ~Javascriptを使えるようにする~
ページ遷移をせずに動的なプロセスを実行する方法はいくつかありますが、今回はJavascriptを用いて実装していきます。そのためにまずはJavascriptを使うことができるように記述を加えていきましょう。Javascriptと聞いて身構えたひともいるかもしれませんが、そんなに難しいプロセスは必要ないため安心してください。
まずは、view/layouts/application.html.erb
の該当箇所に以下の記述を加えていきます。
今回はファイルをダウンロードすることなくオンライン上でjQueryを導入します。
<head>
#省略
<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %> #←この1行を追加
#省略
</head>
#省略
<body>
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
</body>
これでJavascriptの記述が有効になりました。
##実装② ~Viewファイルを整えよう~
Javascriptを使えるようにしたため、次はViweファイルを変更していきます。
まずは、view/likes/の配下に、_like.html.erb
とcreate.js.erb
とdestroy.js.erb```の3つのファイルを作成します。1つ目のファイルはアンダーバー(_)から始まる部分テンプレートであるということ、そして後半2つはhtmlファイルではなくjsファイルであるということに注意しつつファイルを作りましょう。
この後半2つのjsファイルが、likesコントローラーのcreateアクションとdestroyアクションの実行に対応したファイルとなります。
では、作成した3つのファイルにそれぞれ記述を加えていきましょう。
まずは_like.html.erb
ファイルへの記述です。このファイルには、投稿一覧のviewページに記述してある、いいねボタンに関する記述をそのままコピーしてきて貼り付けましょう。
貼り付けた結果は以下のようになります。
<% if user_signed_in? %>
<% if current_user.already_liked?(t) %>
<%= link_to tweet_like_path(id: t.id, tweet_id: t.id), method: :delete, remote: true do %>
<p>いいねを取り消す</p><%= t.likes.count %>
<% end %>
<% else %>
<%= link_to tweet_likes_path(id: t.id, tweet_id: t.id), method: :post, remote: true do %>
<p>いいね</p><%= t.likes.count %>
<% end %>
<% end %>
<% else %>
<p>いいねの数 = </p><%= t.likes.count %>
<% end %>
さて、では2つのjsファイルにも記述を加えていきましょう。
それぞれのファイルに以下の記述を張り付けてください。
なお、@tweet(やt)といった変数は、自身のプロダクトに対応したものに書き換えてください。(変数tはlikes/_like.html.erbで用いた変数と同じものにする)
$('#likes_buttons_<%= @tweet.id %>').html("<%= j(render partial: 'likes/like', locals: {t: @tweet}) %>");
$('#likes_buttons_<%= @tweet.id %>').html("<%= j(render partial: 'likes/like', locals: {t: @tweet}) %>");
最後に、投稿のページ(投稿一覧ページや投稿詳細ページ)にて、_like.html.erbの記述が反映されるように、それぞれ以下の記述を加えてください。
なお、@tweetやtといった変数は、自身のプロダクトに対応したものに書き換えてください。
<div id="likes_buttons_<%= t.id %>">
<%= render partial: 'likes/like', locals: { t: t } %>
</div>
<div id="likes_buttons_<%= @tweet.id %>">
<%= render partial: 'likes/like', locals: { t: @tweet } %>
</div>
さて、ここまでの記述でViewファイルは完成です。
##実装③ ~コントローラーの記述変更~
最後に、likes_controller.rb
の記述を変更していきます。
まずは、viewにあるjsファイルが変数@tweetを受け取ることができるように、@tweetを定義していきます。
また、Javascriptでいいね/いいね取り消しを動的に行えるようにしている状態のため、redirectの記述も消していきます。
変更前と変更後は以下のような感じです。
変更前
def create
like = current_user.likes.create(tweet_id: params[:tweet_id]) #user_idとtweet_idの二つを代入
redirect_back(fallback_location: root_path)
end
def destroy
like = Like.find_by(tweet_id: params[:tweet_id], user_id: current_user.id)
like.destroy
redirect_back(fallback_location: root_path)
end
変更後
def create
@tweet = Tweet.find(params[:tweet_id])
like = current_user.likes.create(tweet_id: params[:tweet_id])
end
def destroy
@tweet = Tweet.find(params[:tweet_id])
like = Like.find_by(tweet_id: params[:tweet_id], user_id: current_user.id)
like.destroy
end
以上で実装は完了です!
rails s
をして、自分のプロダクトでいいねボタンを押してみてください!
ページ遷移せずに、その場でいいねができるようになっているはずです。