You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ajax创建记录后重载ActiveRecordCollectionProxy并禁用点赞按钮

解决Ajax点赞后无需刷新即可禁用按钮的问题

看起来你已经搭好了基础的点赞功能,问题出在Ajax请求成功后没有更新前端按钮状态——目前只有页面加载时会根据服务器数据判断是否禁用按钮,Ajax提交后页面没有同步更新。下面是一步步的修复方案:

1. 先修正模型关联的小问题

首先注意Rails的has_many关联需要用复数形式,否则会引发查询错误:

# app/models/listing.rb
class Listing < ActiveRecord::Base
  has_many :likes, foreign_key: :listing_id, dependent: :destroy # 把like改成likes复数
end

2. 优化视图:给按钮加唯一标识+简化禁用逻辑

修改点赞表单的按钮,给它一个基于listing ID的唯一ID(方便JS精准定位),同时去掉不安全的前端传user_id(改用控制器从current_user获取):

# app/views/likes/_form.html.erb
<%= form_for(Like.new, remote: true) do |f| %>
  <%= f.hidden_field :listing_id, value: listing.id %>
  <%# 不再手动传user_id,控制器通过current_user自动关联 %>
  <% is_liked = listing.likes.pluck(:user_id).include?(current_user.id) %>
  
  <%= f.button "", 
        class: "round-button btn-center #{'disabled' if is_liked}",
        id: "like-button-#{listing.id}", # 唯一ID,JS用来定位
        disabled: is_liked, # 原生disabled属性才会真正禁用按钮
        data: { disable_with: "<i class='fa fa-spinner fa-spin'></i>" } do %>
    <span class="glyphicon glyphicon-heart"></span>
  <% end %>
<% end %>

3. 优化控制器:增加重复点赞校验+传递@listing给JS

在点赞控制器里,先校验用户是否已经点过赞(避免重复创建记录),同时获取对应的@listing,方便后续JS模板使用:

# app/controllers/likes_controller.rb
class LikesController < ApplicationController
  before_filter :authenticate_user!

  def create
    @listing = Listing.find(params[:like][:listing_id])
    
    # 先检查是否已经点赞,避免重复创建
    if @listing.likes.exists?(user_id: current_user.id)
      respond_to do |format|
        format.js { render :create, status: :unprocessable_entity }
      end
      return
    end

    # 用current_user关联创建点赞,自动设置user_id
    @like = current_user.likes.build(listing: @listing)
    
    respond_to do |format|
      if @like.save
        current_user.create_activity(@like, "like")
        format.js
      else
        format.html { redirect_to root_url, notice: "Unable to proceed" }
        format.js
      end
    end
  end
  [...] 
end

4. 创建JS模板:Ajax成功后实时禁用按钮

新建app/views/likes/create.js.erb文件,这是Ajax请求成功后会自动执行的JS代码,用来更新按钮状态:

// 定位当前listing的点赞按钮
const likeButton = document.getElementById('like-button-<%= @listing.id %>');

// 禁用按钮+添加禁用样式
likeButton.disabled = true;
likeButton.classList.add('disabled');

// 可选:把图标改成实心爱心(视觉反馈)
likeButton.innerHTML = '<span class="glyphicon glyphicon-heart"></span>';

如果要处理重复点赞的错误情况,可以再写一段错误状态下的JS:

// app/views/likes/create.js.erb(当status为:unprocessable_entity时)
alert('你已经给这个内容点过赞啦!');
// 恢复按钮的可点击状态
const likeButton = document.getElementById('like-button-<%= @listing.id %>');
likeButton.disabled = false;
likeButton.innerHTML = '<span class="glyphicon glyphicon-heart"></span>';

原理说明

  • 页面加载时,服务器根据用户是否已点赞渲染按钮的初始状态;
  • 用户点击按钮后,Ajax提交请求到控制器,控制器校验并创建点赞记录;
  • 成功后执行create.js.erb,直接操作DOM禁用对应按钮,无需刷新页面;
  • 增加重复点赞校验,既避免数据库冗余,也给用户更友好的反馈。

内容的提问来源于stack exchange,提问作者Obed Lorisson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 03:44:32