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

使用acts_as_votable实现无刷新点赞时模板缺失问题求助

无刷新点赞功能的模板缺失问题排查

已基于acts_as_votable gem实现页面刷新点赞,现在尝试通过AJAX实现无刷新点赞,项目存在partial嵌套结构,当前遇到ActionView::MissingTemplate错误,提示找不到events/favorite.js.erb模板,已尝试多路径放置文件仍未解决,以下是相关代码、错误信息及排查思路:


相关代码

1. events/index.html.erb(渲染partial)

<div class="event-list-wrapper">
  <% @events.upcoming_events.each do |event| %>
    <%= render 'event', event: event %>
  <% end %>
</div> 

2. _event.html.erb partial

<div class="card shadow rounded mb-3">
  <div class="top-card">
    <div class="card-image">
      <% if event.event_image.attached? %>
        <%= link_to image_tag(event.event_image, class: "card-img-top event-index-image").html_safe, event %>
      <% else %>
        <img src="https://dancewise.s3.amazonaws.com/Blank+Event+Image.png" class="card-img-top even-size-event">
      <% end %>
    </div>
    <div class="heart-container">
      <%= render "events/favorite-link", event: event %>
    </div>
  </div>
<%= content_tag "div", id: "upvote-#{event.id}" do %>
  <%= link_to upvote_event_path(event), method: :get, remote: true do %>
    <% if current_user.voted_up_on? event %>
      <%= link_to upvote_event_path(event), method: :patch do %>
        <svg 
          xmlns="http://www.w3.org/2000/svg" 
          viewBox="0 0 24 24" 
          fill="#ff2929" 
          stroke-width="1.2"
          stroke="#f2f2f2" 
          class="w-6 h-6">
          <path d="M11.645 20.91l-.007-.003-.022-.012a15.247 15.247 0 01-.383-.218 25.18 25.18 0 01-4.244-3.17C4.688 15.36 2.25 12.174 2.25 8.25 2.25 5.322 4.714 3 7.688 3A5.5 5.5 0 0112 5.052 5.5 5.5 0 0116.313 3c2.973 0 5.437 2.322 5.437 5.25 0 3.925-2.438 7.111-4.739 9.256a25.175 25.175 0 01-4.244 3.17 15.247 15.247 0 01-.383.219l-.022.012-.007.004-.003.001a.752.752 0 01-.704 0l-.003-.001z" />
        </svg>
      <% end %>
    <% else %>
      <%= link_to upvote_event_path(event), method: :patch do %>
        <svg 
          xmlns="http://www.w3.org/2000/svg" 
          fill="#000000" 
          fill-opacity="0.5" 
          viewBox="0 0 24 24"
          data-user-logged-in="<%= user_signed_in? %>"
          stroke-width="1.2" 
          stroke="#f2f2f2" 
          class="w-6 h-6">
          <path stroke-linecap="round" stroke-linejoin="round" d="M21 8.25c0-2.485-2.099-4.5-4.688-4.5-1.935 0-3.597 1.126-4.312 2.733-.715-1.607-2.377-2.733-4.313-2.733C5.1 3.75 3 5.765 3 8.25c0 7.22 9 12 9 12s9-4.78 9-12z" />
        </svg>
      <% end %>
    <% end %>
  <% end %>
<% end %>

4. favorite.js.erb 代码

document.getElementById("upvote-<%= @event.id %>").innerHTML = "<%= j render "events/favorite-link", event: event %>";

5. events_controller.rb 的 upvote 方法

def upvote
  if current_user.voted_up_on? @event
    @event.unvote_by current_user
  else
    @event.upvote_by current_user
  end
  render "favorite.js.erb"
end

6. routes.rb 相关代码

resources :events do
  member do
    get "upvote", to: "events#upvote"
  end
end

文件放置路径

  • /Users/ogarocious/Desktop/RubyWorld/wherecanwedance-dw/app/views/favorite.js.erb
  • /Users/ogarocious/Desktop/RubyWorld/wherecanwedance-dw/app/views/events/favorite.js.erb

错误日志

01:58:49 web.1  | Completed 500 Internal Server Error in 24ms (ActiveRecord: 4.5ms | Allocations: 10048)
01:58:49 web.1  | 
01:58:49 web.1  | ActionView::MissingTemplate (Missing template events/favorite.js.erb, application/favorite.js.erb with {:locale=>[:en], :formats=>[:html], :variants=>[], :handlers=>[:raw, :erb, :html, :builder, :ruby, :jbuilder]}.
01:58:49 web.1  | 
01:58:49 web.1  | Searched in:
01:58:49 web.1  |   * "/Users/ogarocious/Desktop/RubyWorld/wherecanwedance-dw/app/views"
01:58:49 web.1  |   * "/Users/ogarocious/.rvm/gems/ruby-3.0.2/gems/devise-4.8.1/app/views"
01:58:49 web.1  |   * "/Users/ogarocious/.rvm/gems/ruby-3.0.2/gems/actiontext-7.0.4/app/views"
01:58:49 web.1  |   * "/Users/ogarocious/.rvm/gems/ruby-3.0.2/gems/actionmailbox-7.0.4/app/views"
01:58:49 web.1  | 
01:58:49 web.1  | app/controllers/events_controller.rb:19:in `upvote'

排查思路

  1. 修正请求格式:错误日志显示请求格式为[:html],但AJAX需要js格式。可以:

    • 修改路由为get "upvote", to: "events#upvote", format: :js
    • 或在link_to中指定格式:upvote_event_path(event, format: :js)
  2. 明确模板渲染路径:在控制器中指定完整路径和格式,避免歧义:

    # 如果模板在events目录下
    render template: "events/favorite", formats: :js
    # 如果模板在根视图目录
    render template: "favorite", formats: :js
    
  3. 修复JS模板变量错误:favorite.js.erb中使用了未定义的event变量,应改为控制器中的@event:

    document.getElementById("upvote-<%= @event.id %>").innerHTML = "<%= j render "events/favorite-link", event: @event %>";
    
  4. 调整路由请求方法:点赞/取消点赞是修改操作,不应使用get,改为patch:

    resources :events do
      member do
        patch "upvote", to: "events#upvote"
      end
    end
    
  5. 清理嵌套的link_to:当前代码中嵌套了两层link_to,会生成无效的嵌套<a>标签,导致AJAX请求失效,重构为:

    <%= content_tag "div", id: "upvote-#{event.id}" do %>
      <% if current_user.voted_up_on? event %>
        <%= link_to upvote_event_path(event, format: :js), method: :patch, remote: true do %>
          <!-- 已点赞SVG -->
        <% end %>
      <% else %>
        <%= link_to upvote_event_path(event, format: :js), method: :patch, remote: true do %>
          <!-- 未点赞SVG -->
        <% end %>
      <% end %>
    <% end %>
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 07:15:56