#非同期通信でのいいね機能
しばらくJavaに浮気をしていて久しぶりに個人アプリ(Ruby)に触れたら結構記憶が飛んでたので思い出すためにいいね機能を搭載してみました。
いろいろな記事を見ながら実装したので自分用に纏めるメモです。
userとarticleを紐付けてボタンを押すといいねができるようになるまで。
注意点...すでにアプリとしての形はある程度できている状態からの説明です
##①モデル、テーブルの追加
rails g model favorite をしてマイグレーションファイルを修正
class CreateFavorites < ActiveRecord::Migration[5.2]
def change
create_table :favorites do |t|
t.references :user, null: false, foreign_key: true
t.references :article, null: false, foreign_key: true
t.timestamps
end
end
end
その後rails db:migrate
モデルにアソシエーションを追記
has_many :favorites, dependent: :destroy
has_many :favorite_articles, through: :favorites, source: :article
has_many :favorites, dependent: :destroy
has_many :favorite_users, through: :favorites, source: :user
belongs_to :user
belongs_to :article
validates :user_id, presence: true
validates :article_id, presence: true
validates_uniqueness_of :article_id, scope: :user_id
###②コントローラの追加(ついでにルーティング)
rails g controller favorites でfavoriteコントローラを追加する
そして以下のように追記
before_action :set_article, only: [:create, :destroy]
def create
@favorite = Favorite.create(user_id: current_user.id, article_id: @article.id)
end
def destroy
@favorite = Favorite.find_by(user_id: current_user.id, article_id: @article.id)
@favorite.destroy
end
private
def set_article
@article = Article.find(params[:article_id])
end
ルーティングも編集
resources :articles do
resources :favorites , only: [:create, :destroy] #追記
end
####③ビューの編集
いいねをするボタンを部分テンプレートを用いて追加
.content
= render "layouts/favorite", article: @article
.content__favorite{id: "like-#{@article.id}"}
- if Favorite.find_by(user_id: current_user.id, article_id: article.id)
.btn1
= link_to article_favorite_path(article.id, current_user.id), method: :delete, class: "like-delete", remote: true do
= icon('fa', 'star')
お気に入り追加済み
= article.favorites.length
- else
.btn2
= link_to article_favorites_path(article.id), method: :post, class: "like-create", remote: true do
= icon('fa', 'star')
お気に入り
= article.favorites.length
remote:trueをつけるとリンクを踏んだ時ajaxが起動する。
####④ボタンを非同期通信にする
create.js.haml と destroy.js.hamlファイル作成し追記
$("#like-#{@article.id}").html("#{j(render partial: 'layouts/favorite', locals: { article: @article })}");
$("#like-#{@article.id}").html("#{j(render partial: 'layouts/favorite', locals: { article: @article })}");
ボタンにつけたidを参照してボタンが押されるとファイルを再読み込みするようにしてあるっぽい。
あとはボタンの見た目とかを綺麗に整えたら完成。
参考にした記事
https://qiita.com/yummy888/items/2b7708a498861e5ba733
https://qiita.com/nojinoji/items/2c66499848d882c31ffa