【问题标题】:Rails ajax callback after link_to remote链接到远程之后的Rails ajax回调
【发布时间】:2013-09-10 20:25:44
【问题描述】:

我正试图弄清楚这个 ajax 回调业务,但没有任何运气让它发挥作用。我看过大量的 SO 问题、教程等,但显然没有掌握它是如何工作的。我正在尝试更新包含部分的 div 的内容。这是一个标准的like/unlike 类型函数,用户将点击链接,它应该通过ajax 更新图标。我的 ajax 远程请求工作正常,但我无法让回调工作。这是我的show.html.erb 文件:

<table class="v-table">
    <tr>    
        <td>
            <div class="favorite">
                    <%= render 'vendors/favorite' %>
            </div>
        </td>
        <td><h2><%= image_tag @vendor.image_url %></h2></td>
        <td><%= @vendor.address %></td>
    </tr>
</table>

这是部分favorite

<% if current_user.voted_for?(@vendor) %>
    <%= link_to image_tag("Heart (2).png"), 
        { :controller => :vendors, 
        :action => 'vote_against_vendor', :vendor_id => @vendor.id},
        { :method => 'delete', :remote => true }%>
<% else %>
    <%= link_to image_tag("Heart (1).png"), 
        { :controller => :vendors, 
        :action => 'vote_for_vendor', :vendor_id => @vendor.id},
        { :method => 'post', :remote => true} %>
<% end %>

这是我的相关控制器操作:

respond_to :js

def show

    @vendor = Vendor.find_by_id(params[:id])
end

def vote_for_vendor

    vendor = Vendor.find(params[:vendor_id])
    current_user.vote_for(vendor)
    render :toggle
end

def vote_against_vendor

    vendor = Vendor.find(params[:vendor_id])
    current_user.unvote_for(vendor)
    render :toggle
end

我的 toggle.js.erb 文件:

$("#favorite").html("<%= escape_javascript render('favorite') %>");

我对使用 js 和 ajax 真的很陌生,请帮助!提前致谢。

错误日志

正确提交远程事务后,我收到此错误:

Rendered vendors/_favorite.html.erb (1.3ms)
  Rendered vendors/toggle.js.erb (2.6ms)
Completed 500 Internal Server Error in 47ms

ActionView::Template::Error (Called id for nil, which would mistakenly be 4 -- if you really wanted the id of nil, use object_id):
    1: <% if current_user.voted_for?(@vendor) %>
    2:  <%= link_to image_tag("Heart (2).png"), 
    3:      { :controller => :vendors, 
    4:      :action => 'vote_against_vendor', :vendor_id => @vendor.id},
  app/views/vendors/_favorite.html.erb:1:in `_app_views_vendors__favorite_html_erb___385976980778737159_2184308220'
  app/views/vendors/toggle.js.erb:1:in `_app_views_vendors_toggle_js_erb___3800164439665893406_2169792040'
  app/controllers/vendors_controller.rb:39:in `vote_for_vendor'


  Rendered /Users/User/.rvm/gems/ruby-2.0.0-p195/gems/actionpack-3.2.13/lib/action_dispatch/middleware/templates/rescues/_trace.erb (1.7ms)
  Rendered /Users/User/.rvm/gems/ruby-2.0.0-p195/gems/actionpack-3.2.13/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (1.3ms)
  Rendered /Users/User/.rvm/gems/ruby-2.0.0-p195/gems/actionpack-3.2.13/lib/action_dispatch/middleware/templates/rescues/template_error.erb within rescues/layout (11.1ms)

不确定这是什么意思:ActionView::Template::Error (Called id for nil, which would mistakenly be 4 -- if you really wanted the id of nil, use object_id):

【问题讨论】:

  • 错误日志说明了什么?
  • 嗯...好点。它是说,Missing template vendors/vote_for_vendor。我以为我对render :toggle说过。
  • 愚蠢的问题(我的)但是请求的类型是什么?是否解释为JS
  • 试试render action: 'toogle'只是为了看看
  • 添加了render action: 'toggle'。发布更新错误。

标签: javascript ruby-on-rails ajax


【解决方案1】:

好的,您需要将模型分配给控制器中的 instance 而不是 local 变量。

@vendor = Vendor.find(params[:vendor_id])

我觉得其余的都不错。

【讨论】:

  • 是的,就是这样。我最初尝试以这种方式设置我的两种 vote_for 方法,但不断收到错误,因此使用局部变量。不管什么原因,这次没有错误。谢谢!
【解决方案2】:

不确定,但我猜您的 toggle.js.erb 文件中可能缺少 render 'vendors/favorite'。其他一切对我来说似乎都很好。

【讨论】:

  • Toggle.js.erb 应该更新 div #favorite,它会渲染 _favorite 部分,不是吗?
  • 是的,可能你需要使用 render partial: :toggel
【解决方案3】:

Ajax 是客户端向服务器发送请求并在多个命令中获得响应的方式。 您应该在客户端进行调用(因此主要使用 javascript 或客户端语言编写代码)。

不要忘记 ajax 默认是异步的(您可以更改它 - 第一次尝试不推荐。实际上,当您将请求发送到服务器时,您会转到代码的下一行,并且不会收到响应准确地在预期的时间,像往常一样)。

这是一个小代码:

var tout;
....

function checkAjax() {
    'use strict';

    var xmlhttp;

    if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safari
        xmlhttp = new XMLHttpRequest();
    } else {// code for IE6, IE5
        xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
    }

    xmlhttp.onreadystatechange = function () {
        if (xmlhttp.readyState === 4 && xmlhttp.status === 200) {
            if (tout) {
                clearTimeout(tout);
            }
// do something
        }
    };

    function ajaxTimeout() {
        xmlhttp.abort();
// write error to client
    }

    clearTimeout(tout); // if tout is global.

    tout = setTimeout(function () {
        ajaxTimeout();
    }, 10000); // 10 seconds, or what you persume to be fine.

    xmlhttp.open("POST", "test.php", true); // it can be "GET" or aspx, or whatever.
    xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");

    xmlhttp.send("");
}

祝你好运!!!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多