-Only reviewers can register as favorites --Implemented favorite function with Ajax communication --Display your favorites list on My Page
Create a favorite table to store which posts and who did your favorites.
rails g model like
db/migrate/20XXXXXXXXXXXX_create_likes.rb
class CreateLikes < ActiveRecord::Migration[6.0]
def change
create_table :likes do |t|
t.references :user, null: false, foreign_key: true
t.references :post, null: false, foreign_key: true
t.timestamps
t.index [:user_id, :post_id], unique: true #Preventing the same user from liking the same post
end
end
end
Use the ** dependent:: destroy option ** to ensure that your favorites are deleted when the post is deleted. Describe in the parent model.
app/models/likei.rb
class Like < ApplicationRecord
belongs_to :user
belongs_to :post
end
app/models/post.rb
class Post < ApplicationRecord
belongs_to :user
has_many :likes, dependent: :destroy
has_one_attached :image
~Abbreviation~
end
app/models/user.rb
class User < ApplicationRecord
~Abbreviation~
has_many :posts
has_many :likes
has_one_attached :image
end
We use routing nesting because we need to indicate which post we like. I wish I could register and delete my favorites, so set the "create action" and "destroy action".
ruby:config.routes.rb
Rails.application.routes.draw do
devise_for :users
root 'posts#top'
resources :posts do
collection do
get 'top'
end
resources :likes, only: [:create, :destroy]
end
resources :users, only: [:show]
end
Define "create action" and "destroy action" in the controller. Favorites can be registered by anyone other than the poster.
app/controllers/likes_controller.rb
class LikesController < ApplicationController
def create
@post = Post.find(params[:post_id])
if @post.user_id != current_user.id #You can register favorites other than your own posts
@like = Like.create(user_id: current_user.id, post_id: @post.id)
end
end
def destroy
@post = Post.find(params[:post_id])
@like = Like.find_by(user_id: current_user.id, post_id: @post.id)
@like.destroy
end
end
The posts that the user has registered as favorites are displayed on My Page. Find the logged-in user's favorites from the Likes table, sort them in descending order, and retrieve the post_ids in an array. The data is stored in @likes by the find method.
app/controllers/users_controller.rb
class UsersController < ApplicationController
def show
@user = User.find(params[:id])
birthday = @user.birthday
date_format = "%Y%m%d"
@age = (Date.today.strftime(date_format).to_i - birthday.strftime(date_format).to_i) / 10000
@posts = @user.posts.order(created_at: :desc)
likes = Like.where(user_id: current_user.id).order(created_at: :desc).pluck(:post_id)
@likes = Post.find(likes)
end
end
Create a partial template to display the part where the favorite button is displayed. It branches depending on whether it is registered as a favorite in the if statement or not.
ruby:app/views/posts/show.html.erb
~Abbreviation~
<div class='star-btn' id="like_<%= @post.id %>">
<%= render "likes/like", post: @post %>
</div>
~Abbreviation~
ruby:app/views/likes/_like.html.erb
<% if !Like.exists?(user_id: current_user.id, post_id: post.id) %>
<%= link_to post_likes_path(post.id), method: :post, remote: true, class:"like-btn" do %>
<i class="fas fa-star star-icon1"></i>
<% end %>
<span class="star-count1"><%= post.likes.count %></span>
<% else %>
<%= link_to post_like_path(post_id: post.id, id: post.likes[0].id), method: :delete, remote: true, class:"like-btn" do %>
<i class="fas fa-star star-icon2"></i>
<% end %>
<span class="star-count2"><%= post.likes.count %></span>
<% end %>
When the favorite button is clicked, the "create action" or "destroy action" is executed, the partial template is updated by Ajax communication, and the favorite button is displayed.
ruby:app/views/likes/create.js.erb
$('#like_<%= @post.id %>').html("<%= j(render partial: 'likes/like', locals: { post: @post }) %>");
ruby:app/views/likes/destroy.js.erb
$('#like_<%= @post.id %>').html("<%= j(render partial: 'likes/like', locals: { post: @post }) %>");
The favorite list of My Page is displayed using the each statement.
ruby:app/views/users/show.html.erb
<% if @likes.present? %>
<ul class="relative-post-lists">
<% @likes.each do |like| %>
<li class='post-list'>
<%= link_to post_path(like.id) do %>
<div class='post-img-content'>
<%= image_tag like.image, class: "post-img" %>
</div>
<div class='relative-post-name'>
Product name:<%= like.name %>
</div>
<div class='relative-item-price'>
<span><%= like.price %>Circle(tax included)</span>
</div>
<div class="relative-post-evaluation">
<span>Evaluation:</span>
<span id="star-rate-<%= like.id %>"></span>
<script>
$('#star-rate-<%= like.id %>').raty({
size: 36,
starOff: "<%= asset_path('star-off.png') %>",
starOn: "<%= asset_path('star-on.png') %>",
starHalf: "<%= asset_path('star-half.png') %>",
half: true,
readOnly: true,
score: <%= like.evaluation %>,
});
</script>
<%= like.evaluation %>
</div>
<div class='user-img-content'>
<%= image_tag like.user.image ,class:"mini-img" if like.user.image.attached? %>
<%= link_to like.user.nickname, user_path(like.user.id) %>
</div>
<div class="relative-post-date">
Updated date:<%= like.created_at.strftime("%Y.%m.%d") %>
</div>
<% end %>
</li>
<% end %>
</ul>
<% end %>
https://qiita.com/manbolila/items/43a04e8d0d5018cf7f62 https://qiita.com/naberina/items/c6b5c8d7756cb882fb20 https://qiita.com/naota7118/items/e009eff939b5a764672d
Recommended Posts