我正在使用rails构建api,并且正在尝试为帖子实现heart / unheart功能。此功能的工作方式是,如果用户对帖子感兴趣,则会在数据库中显示一个新条目(一个用户只能对帖子进行一次处理),如果用户解除了它,则该条目将被删除。目前,我检查前端是否有用户信心,并发送正确的HTTP请求POST或DELETE。但是,它不是很有效率,我想知道是否有更好的方法在后端(控制器或模型)上自动完成它并且只有一个http请求(例如POST)?
heart.rb Model:
class Heart < ApplicationRecord
belongs_to :user
belongs_to :post
validates :post_id, presence: true
validates :user_id, presence: true
validates :user_id, uniqueness: { scope: :post_id }
end
user.rb Model:
class User < ApplicationRecord
has_many :posts, dependent: :destroy
has_many :hearts, dependent: :destroy
def heart!(post)
self.hearts.create!(post_id: post.id)
end
def unheart!(post)
heart = self.hearts.find_by_post_id(post.id)
heart.destroy!
end
end
hearts_controller.rb
class HeartsController < ApplicationController
def heart
@user = current_user
@post = Post.find(params[:post_id])
if @user.heart!(@post)
end
end
def unheart
@user = current_user
@heart = @user.hearts.find_by_post_id(params[:post_id])
@post = Post.find(params[:post_id])
if @heart.destroy!
end
end
end
routes.rb
Rails.application.routes.draw do
match 'heart', to: 'hearts#heart', via: :post
match 'unheart', to: 'hearts#unheart', via: :delete
end
正如您所看到的,我需要首先检查它是否有心,然后才需要发送正确的POST或DELETE请求。有没有更有效的方法只发送一个请求然后检查它在rails内是否有心并且从一个控制器发布/删除?
答案 0 :(得分:1)
我建议您只有一条路线可以监听帖子的PATCH
方法。类似的东西:
patch '/posts/:id/heart' => 'posts#heart_post', as: :heart_post
而不是HeartsController
,在heart_post
中实施PostsController
操作,接受您的帖子和当前用户并发布您的帖子(无论当前状态如何,是否有心)。
def heart_post
@post = Post.find(params[:id])
@post.heart_action(@current_user.id)
# whatever you want to render
end
然后,您的Post
模型将包含自身的逻辑,并且知道它是否需要执行心脏或无心的动作。
def heart_action (user_id)
heart = Heart.find_by(user_id: user_id, post_id: self.id)
if heart
heart.destroy
else
Heart.create(user_id: user_id, link_id: self.id)
end
end
此操作应该只有一条路线。