あおい(https://twitter.com/aoi_engineer )です。
Ruby on Railsでお気に入り機能を実装したので手順を公開します。
実装したい機能
- お気に入り登録・解除できること
- 未ログイン時にはお気に入りできない
- 未ログイン時にはお気に入り一覧ページにアクセスできない
- お気に入りボタンをクリックするとAjax通信でデータ保存ができる
1. ブランチ作成
git checkout -b favorites
2. Favoriteモデルの作成
% rails g model Favorite user_id:integer post_id:integer
3. migrationファイルの編集
def change
create_table :favorites do |t|
t.integer :user_id
t.integer :post_id
t.timestamps
end
add_index :favorites, [:user_id, :post_id], unique: true # 追記
end
データベースに反映させます。
% rails db:migrate
4. 関連付け
favorite.rb
class Favorite < ApplicationRecord
belongs_to :user
belongs_to :post
end
user.rb
has_many :favorites, dependent: :destroy
post.rb
has_many :favorites, dependent: :destroy
5. バリデーションの追加
favorite.rb
belongs_to :user
belongs_to :post
validates :user_id, presence: true # 追記
validates :post_id, presence: true # 追記
6. コントローラー作成
% rails generate controller Favorites
7. コントローラー編集
favorites_controller.rb
class FavoritesController < ApplicationController
before_action :authenticate_user!
def create
@post = Post.find(params[:post_id])
@user = @post.user
current_user.favorite(@post)
respond_to do |format|
format.html { redirect_to request.referrer || root_url }
format.js
end
end
def destroy
@post = Post.find(params[:post_id])
current_user.favorites.find_by(post_id: @post.id).destroy
respond_to do |format|
format.html { redirect_to request.referrer || root_url }
format.js
end
end
end
8. ルート編集
route.rb
post "favorites/:post_id/create" => "favorites#create"
delete "favorites/:post_id/destroy" => "favorites#destroy"
end
9. お気に入り登録のメソッドを作成
user.rb
def favorite(post)
Favorite.create!(user_id: id, post_id: post.id)
end
# 投稿のお気に入り解除する
def unfavorite(post)
Favorite.find_by(user_id: id, post_id: post.id).destroy
end
# 現在のユーザーがお気に入り登録してたらtrueを返す
def favorite?(post)
!Favorite.find_by(user_id: id, post_id: psot.id).nil?
end
10. Ajaxの実装
- app/views/favorites/create.js.erb (新規)
- app/views/favorites/destroy.js.erb (新規)
create.js.erb
$("#favorite-<%= @post.id %>").html("<%= escape_javascript(render('users/unfavorite')) %>");
destroy.js.erb
$("#favorite-<%= @post.id %>").html("<%= escape_javascript(render('users/favorite')) %>");
11. お気に入りフォームの作成
app/views/users/_favorite_form.html.erb (新規)
app/views/users/_favorite_form.html.erb
<div id="favorite-<%= @post.id %>">
<% if !current_user.nil? && current_user.favorite?(@post) %>
<%= render 'users/unfavorite' %>
<% else %>
<%= render 'users/favorite' %>
<% end %>
</div>
12. それぞれのボタンを作成
app/views/users/_favorite.html.erb (新規)
app/views/users/_favorite.html.erb
<%= link_to "/favorites/#{@post.id}/create", method: :post, class: 'like', remote: true do %>
<div class="favorite">お気に入りに登録</div>
<% end %>
app/views/users/_unfavorite.html.erb (新規)
app/views/users/_unfavorite.html.erb
<%= link_to "/favorites/#{@post.id}/destroy", method: :post, class: 'like', remote: true do %>
<div class="unfavorite">お気に入り登録済み</div>
<% end %>
13. ボタンによって色を変更
app/assets/stylesheets/~.scss
like {
color: gray;
}
unlike {
color: red;
}
14. 表示させたいページに追加
~.erb
<%= render 'users/favorite_form' %>
以上です!
参考になった方はLGTMお願いします🙇♂️