能否在as_json中结合current_user判断用户是否点赞指定帖子?
解决方法
嘿,我明白你的困扰了!直接用self.likes.user肯定不行,因为self.likes返回的是这篇帖子的所有点赞记录集合,集合本身没有user这个方法。要在as_json里判断当前用户是否点赞,核心是把当前用户传递到模型的as_json方法中,然后针对性查询。下面给你两种实用的方案:
方案一:添加自定义方法,在as_json中注入结果
首先,在Post模型里定义一个方法来检查当前用户是否点赞,然后在as_json里把这个结果包含进去:
# app/models/post.rb def as_json(options = {}) # 从options里取出传入的当前用户 current_user = options[:current_user] super(options.merge( # 把自定义方法加入返回字段 methods: [:liked_by_current_user], # 可以在这里继续添加你需要的其他配置,比如include、except等 except: [:created_at, :updated_at] )) end def liked_by_current_user # 这里需要注意:要确保@current_user_id已经被赋值 @current_user_id.present? && likes.exists?(user_id: @current_user_id) end # 可选:添加一个方法来设置当前用户ID,或者直接在as_json里处理 def set_current_user(user) @current_user_id = user.id end
然后在控制器里调用as_json时,把当前用户传进去:
# app/controllers/posts_controller.rb def show @post = Post.find(params[:id]) # 方式一:直接传current_user到options render json: @post.as_json(current_user: current_user) # 方式二:先设置当前用户再调用(如果用了set_current_user方法) # @post.set_current_user(current_user) # render json: @post.as_json end
方案二:直接在as_json中拼接判断结果
如果不想额外加方法,也可以直接在as_json里完成判断逻辑,更简洁:
# app/models/post.rb def as_json(options = {}) current_user = options[:current_user] # 先调用super获取基础的JSON结构 base_json = super(options) # 新增一个liked字段,判断当前用户是否点赞 base_json[:liked] = if current_user.present? likes.exists?(user_id: current_user.id) else false end base_json end
调用方式和方案一一样,在控制器里传入current_user:
render json: @post.as_json(current_user: current_user)
关键说明
- 为什么不能直接在模型里用
current_user?因为current_user是控制器层面的辅助方法,模型默认无法访问,必须通过参数传递进去。 - 用
likes.exists?(user_id: current_user.id)比likes.find_by(user_id: current_user.id)更高效,因为exists?只检查是否存在,不会加载整个记录。
内容的提问来源于stack exchange,提问作者Krilo Max
相关产品推荐
相关产品推荐

