1
1

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 3 years have passed since last update.

【Rails】お気に入り機能の実装手順を公開!!【簡単にできます】

Last updated at Posted at 2020-11-18

あおい(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お願いします🙇‍♂️

1
1
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
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?